@blackglory/match 0.3.5 → 0.4.0

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 (242) hide show
  1. package/README.md +21 -32
  2. package/lib/index.d.ts +17 -0
  3. package/lib/index.js +18 -0
  4. package/lib/index.js.map +1 -0
  5. package/lib/{es2015/match-element.d.ts → match-element.d.ts} +1 -1
  6. package/lib/match-element.js +18 -0
  7. package/lib/match-element.js.map +1 -0
  8. package/lib/{es2015/match.d.ts → match.d.ts} +1 -1
  9. package/lib/match.js +18 -0
  10. package/lib/match.js.map +1 -0
  11. package/lib/{es2015/matchers → matchers}/any-of.d.ts +1 -1
  12. package/lib/matchers/any-of.js +6 -0
  13. package/lib/matchers/any-of.js.map +1 -0
  14. package/lib/{es2015/matchers → matchers}/child-nodes.d.ts +1 -1
  15. package/lib/matchers/child-nodes.js +24 -0
  16. package/lib/matchers/child-nodes.js.map +1 -0
  17. package/lib/{es2015/matchers → matchers}/children.d.ts +1 -1
  18. package/lib/matchers/children.js +24 -0
  19. package/lib/matchers/children.js.map +1 -0
  20. package/lib/{es2015/matchers → matchers}/css.d.ts +1 -1
  21. package/lib/matchers/css.js +14 -0
  22. package/lib/matchers/css.js.map +1 -0
  23. package/lib/{es2015/matchers → matchers}/element.d.ts +1 -1
  24. package/lib/matchers/element.js +30 -0
  25. package/lib/matchers/element.js.map +1 -0
  26. package/lib/{es2018/matchers → matchers}/multiple.d.ts +1 -1
  27. package/lib/matchers/multiple.js +39 -0
  28. package/lib/matchers/multiple.js.map +1 -0
  29. package/lib/{es2015/matchers → matchers}/node.d.ts +1 -1
  30. package/lib/matchers/node.js +27 -0
  31. package/lib/matchers/node.js.map +1 -0
  32. package/lib/{es2015/matchers → matchers}/optional.d.ts +1 -1
  33. package/lib/matchers/optional.js +5 -0
  34. package/lib/matchers/optional.js.map +1 -0
  35. package/lib/{es2015/matchers → matchers}/repeat.d.ts +1 -1
  36. package/lib/matchers/repeat.js +16 -0
  37. package/lib/matchers/repeat.js.map +1 -0
  38. package/lib/{es2015/matchers → matchers}/tap.d.ts +1 -1
  39. package/lib/matchers/tap.js +8 -0
  40. package/lib/matchers/tap.js.map +1 -0
  41. package/lib/{es2018/matchers → matchers}/text-content-equals.d.ts +1 -1
  42. package/lib/matchers/text-content-equals.js +16 -0
  43. package/lib/matchers/text-content-equals.js.map +1 -0
  44. package/lib/{es2018/matchers → matchers}/text-content-includes.d.ts +1 -1
  45. package/lib/matchers/text-content-includes.js +16 -0
  46. package/lib/matchers/text-content-includes.js.map +1 -0
  47. package/lib/{es2015/matchers → matchers}/text-content-matches.d.ts +1 -1
  48. package/lib/matchers/text-content-matches.js +12 -0
  49. package/lib/matchers/text-content-matches.js.map +1 -0
  50. package/lib/{es2015/matchers → matchers}/text-node.d.ts +1 -1
  51. package/lib/matchers/text-node.js +30 -0
  52. package/lib/matchers/text-node.js.map +1 -0
  53. package/lib/{es2015/matchers → matchers}/xpath.d.ts +1 -1
  54. package/lib/{es2015/matchers → matchers}/xpath.js +7 -11
  55. package/lib/matchers/xpath.js.map +1 -0
  56. package/lib/types.d.ts +18 -0
  57. package/lib/types.js +2 -0
  58. package/lib/types.js.map +1 -0
  59. package/lib/{es2015/utils → utils}/concat.js +1 -5
  60. package/lib/utils/concat.js.map +1 -0
  61. package/lib/{es2015/utils → utils}/match-multiple.d.ts +4 -1
  62. package/lib/utils/match-multiple.js +20 -0
  63. package/lib/utils/match-multiple.js.map +1 -0
  64. package/lib/{es2015/utils → utils}/match-one-by-one.d.ts +1 -1
  65. package/lib/{es2015/utils → utils}/match-one-by-one.js +9 -9
  66. package/lib/utils/match-one-by-one.js.map +1 -0
  67. package/lib/utils/merge-in-place.d.ts +1 -0
  68. package/lib/{es2015/utils → utils}/merge-in-place.js +5 -9
  69. package/lib/utils/merge-in-place.js.map +1 -0
  70. package/lib/utils/next-element-sibling.js +7 -0
  71. package/lib/utils/next-element-sibling.js.map +1 -0
  72. package/lib/utils/next-sibling.js +7 -0
  73. package/lib/utils/next-sibling.js.map +1 -0
  74. package/package.json +34 -49
  75. package/src/index.ts +18 -0
  76. package/src/match-element.ts +23 -0
  77. package/src/match.ts +23 -0
  78. package/src/matchers/any-of.ts +13 -0
  79. package/src/matchers/child-nodes.ts +33 -0
  80. package/src/matchers/children.ts +35 -0
  81. package/src/matchers/css.ts +24 -0
  82. package/src/matchers/element.ts +49 -0
  83. package/src/matchers/multiple.ts +59 -0
  84. package/src/matchers/node.ts +50 -0
  85. package/src/matchers/optional.ts +6 -0
  86. package/src/matchers/repeat.ts +25 -0
  87. package/src/matchers/tap.ts +12 -0
  88. package/src/matchers/text-content-equals.ts +28 -0
  89. package/src/matchers/text-content-includes.ts +28 -0
  90. package/src/matchers/text-content-matches.ts +20 -0
  91. package/src/matchers/text-node.ts +52 -0
  92. package/src/matchers/xpath.ts +54 -0
  93. package/src/types.ts +39 -0
  94. package/src/utils/concat.ts +9 -0
  95. package/src/utils/match-multiple.ts +27 -0
  96. package/src/utils/match-one-by-one.ts +47 -0
  97. package/src/utils/merge-in-place.ts +26 -0
  98. package/src/utils/next-element-sibling.ts +10 -0
  99. package/src/utils/next-sibling.ts +7 -0
  100. package/dist/es2015/index.min.mjs +0 -2
  101. package/dist/es2015/index.min.mjs.map +0 -1
  102. package/dist/es2015/index.mjs +0 -4445
  103. package/dist/es2015/index.mjs.map +0 -1
  104. package/dist/es2015/index.umd.js +0 -4471
  105. package/dist/es2015/index.umd.js.map +0 -1
  106. package/dist/es2015/index.umd.min.js +0 -2
  107. package/dist/es2015/index.umd.min.js.map +0 -1
  108. package/dist/es2018/index.min.mjs +0 -2
  109. package/dist/es2018/index.min.mjs.map +0 -1
  110. package/dist/es2018/index.mjs +0 -4453
  111. package/dist/es2018/index.mjs.map +0 -1
  112. package/dist/es2018/index.umd.js +0 -4479
  113. package/dist/es2018/index.umd.js.map +0 -1
  114. package/dist/es2018/index.umd.min.js +0 -2
  115. package/dist/es2018/index.umd.min.js.map +0 -1
  116. package/lib/es2015/index.d.ts +0 -17
  117. package/lib/es2015/index.js +0 -38
  118. package/lib/es2015/index.js.map +0 -1
  119. package/lib/es2015/match-element.js +0 -22
  120. package/lib/es2015/match-element.js.map +0 -1
  121. package/lib/es2015/match.js +0 -22
  122. package/lib/es2015/match.js.map +0 -1
  123. package/lib/es2015/matchers/any-of.js +0 -10
  124. package/lib/es2015/matchers/any-of.js.map +0 -1
  125. package/lib/es2015/matchers/child-nodes.js +0 -23
  126. package/lib/es2015/matchers/child-nodes.js.map +0 -1
  127. package/lib/es2015/matchers/children.js +0 -23
  128. package/lib/es2015/matchers/children.js.map +0 -1
  129. package/lib/es2015/matchers/css.js +0 -18
  130. package/lib/es2015/matchers/css.js.map +0 -1
  131. package/lib/es2015/matchers/element.js +0 -34
  132. package/lib/es2015/matchers/element.js.map +0 -1
  133. package/lib/es2015/matchers/multiple.d.ts +0 -10
  134. package/lib/es2015/matchers/multiple.js +0 -42
  135. package/lib/es2015/matchers/multiple.js.map +0 -1
  136. package/lib/es2015/matchers/node.js +0 -31
  137. package/lib/es2015/matchers/node.js.map +0 -1
  138. package/lib/es2015/matchers/optional.js +0 -9
  139. package/lib/es2015/matchers/optional.js.map +0 -1
  140. package/lib/es2015/matchers/repeat.js +0 -20
  141. package/lib/es2015/matchers/repeat.js.map +0 -1
  142. package/lib/es2015/matchers/tap.js +0 -12
  143. package/lib/es2015/matchers/tap.js.map +0 -1
  144. package/lib/es2015/matchers/text-content-equals.d.ts +0 -7
  145. package/lib/es2015/matchers/text-content-equals.js +0 -20
  146. package/lib/es2015/matchers/text-content-equals.js.map +0 -1
  147. package/lib/es2015/matchers/text-content-includes.d.ts +0 -7
  148. package/lib/es2015/matchers/text-content-includes.js +0 -20
  149. package/lib/es2015/matchers/text-content-includes.js.map +0 -1
  150. package/lib/es2015/matchers/text-content-matches.js +0 -16
  151. package/lib/es2015/matchers/text-content-matches.js.map +0 -1
  152. package/lib/es2015/matchers/text-node.js +0 -34
  153. package/lib/es2015/matchers/text-node.js.map +0 -1
  154. package/lib/es2015/matchers/xpath.js.map +0 -1
  155. package/lib/es2015/types.d.ts +0 -18
  156. package/lib/es2015/types.js +0 -3
  157. package/lib/es2015/types.js.map +0 -1
  158. package/lib/es2015/utils/concat.js.map +0 -1
  159. package/lib/es2015/utils/match-multiple.js +0 -21
  160. package/lib/es2015/utils/match-multiple.js.map +0 -1
  161. package/lib/es2015/utils/match-one-by-one.js.map +0 -1
  162. package/lib/es2015/utils/merge-in-place.d.ts +0 -5
  163. package/lib/es2015/utils/merge-in-place.js.map +0 -1
  164. package/lib/es2015/utils/next-element-sibling.js +0 -11
  165. package/lib/es2015/utils/next-element-sibling.js.map +0 -1
  166. package/lib/es2015/utils/next-sibling.js +0 -11
  167. package/lib/es2015/utils/next-sibling.js.map +0 -1
  168. package/lib/es2018/index.d.ts +0 -17
  169. package/lib/es2018/index.js +0 -38
  170. package/lib/es2018/index.js.map +0 -1
  171. package/lib/es2018/match-element.d.ts +0 -4
  172. package/lib/es2018/match-element.js +0 -22
  173. package/lib/es2018/match-element.js.map +0 -1
  174. package/lib/es2018/match.d.ts +0 -4
  175. package/lib/es2018/match.js +0 -22
  176. package/lib/es2018/match.js.map +0 -1
  177. package/lib/es2018/matchers/any-of.d.ts +0 -6
  178. package/lib/es2018/matchers/any-of.js +0 -10
  179. package/lib/es2018/matchers/any-of.js.map +0 -1
  180. package/lib/es2018/matchers/child-nodes.d.ts +0 -2
  181. package/lib/es2018/matchers/child-nodes.js +0 -27
  182. package/lib/es2018/matchers/child-nodes.js.map +0 -1
  183. package/lib/es2018/matchers/children.d.ts +0 -2
  184. package/lib/es2018/matchers/children.js +0 -27
  185. package/lib/es2018/matchers/children.js.map +0 -1
  186. package/lib/es2018/matchers/css.d.ts +0 -3
  187. package/lib/es2018/matchers/css.js +0 -18
  188. package/lib/es2018/matchers/css.js.map +0 -1
  189. package/lib/es2018/matchers/element.d.ts +0 -4
  190. package/lib/es2018/matchers/element.js +0 -34
  191. package/lib/es2018/matchers/element.js.map +0 -1
  192. package/lib/es2018/matchers/multiple.js +0 -42
  193. package/lib/es2018/matchers/multiple.js.map +0 -1
  194. package/lib/es2018/matchers/node.d.ts +0 -4
  195. package/lib/es2018/matchers/node.js +0 -31
  196. package/lib/es2018/matchers/node.js.map +0 -1
  197. package/lib/es2018/matchers/optional.d.ts +0 -2
  198. package/lib/es2018/matchers/optional.js +0 -9
  199. package/lib/es2018/matchers/optional.js.map +0 -1
  200. package/lib/es2018/matchers/repeat.d.ts +0 -2
  201. package/lib/es2018/matchers/repeat.js +0 -20
  202. package/lib/es2018/matchers/repeat.js.map +0 -1
  203. package/lib/es2018/matchers/tap.d.ts +0 -2
  204. package/lib/es2018/matchers/tap.js +0 -12
  205. package/lib/es2018/matchers/tap.js.map +0 -1
  206. package/lib/es2018/matchers/text-content-equals.js +0 -20
  207. package/lib/es2018/matchers/text-content-equals.js.map +0 -1
  208. package/lib/es2018/matchers/text-content-includes.js +0 -20
  209. package/lib/es2018/matchers/text-content-includes.js.map +0 -1
  210. package/lib/es2018/matchers/text-content-matches.d.ts +0 -6
  211. package/lib/es2018/matchers/text-content-matches.js +0 -16
  212. package/lib/es2018/matchers/text-content-matches.js.map +0 -1
  213. package/lib/es2018/matchers/text-node.d.ts +0 -4
  214. package/lib/es2018/matchers/text-node.js +0 -34
  215. package/lib/es2018/matchers/text-node.js.map +0 -1
  216. package/lib/es2018/matchers/xpath.d.ts +0 -3
  217. package/lib/es2018/matchers/xpath.js +0 -34
  218. package/lib/es2018/matchers/xpath.js.map +0 -1
  219. package/lib/es2018/types.d.ts +0 -18
  220. package/lib/es2018/types.js +0 -3
  221. package/lib/es2018/types.js.map +0 -1
  222. package/lib/es2018/utils/concat.d.ts +0 -1
  223. package/lib/es2018/utils/concat.js +0 -14
  224. package/lib/es2018/utils/concat.js.map +0 -1
  225. package/lib/es2018/utils/match-multiple.d.ts +0 -2
  226. package/lib/es2018/utils/match-multiple.js +0 -21
  227. package/lib/es2018/utils/match-multiple.js.map +0 -1
  228. package/lib/es2018/utils/match-one-by-one.d.ts +0 -2
  229. package/lib/es2018/utils/match-one-by-one.js +0 -38
  230. package/lib/es2018/utils/match-one-by-one.js.map +0 -1
  231. package/lib/es2018/utils/merge-in-place.d.ts +0 -5
  232. package/lib/es2018/utils/merge-in-place.js +0 -31
  233. package/lib/es2018/utils/merge-in-place.js.map +0 -1
  234. package/lib/es2018/utils/next-element-sibling.d.ts +0 -1
  235. package/lib/es2018/utils/next-element-sibling.js +0 -11
  236. package/lib/es2018/utils/next-element-sibling.js.map +0 -1
  237. package/lib/es2018/utils/next-sibling.d.ts +0 -1
  238. package/lib/es2018/utils/next-sibling.js +0 -11
  239. package/lib/es2018/utils/next-sibling.js.map +0 -1
  240. /package/lib/{es2015/utils → utils}/concat.d.ts +0 -0
  241. /package/lib/{es2015/utils → utils}/next-element-sibling.d.ts +0 -0
  242. /package/lib/{es2015/utils → utils}/next-sibling.d.ts +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-content-equals.js","sourceRoot":"","sources":["../../src/matchers/text-content-equals.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAO5C,MAAM,UAAU,iBAAiB,CAC/B,IAAY,EACZ,EACE,aAAa,GAAG,IAAI,EACpB,IAAI,GAAG,KAAK,KACiB,EAAE;IAEjC,OAAO,CAAC,IAAU,EAAE,EAAE;QACpB,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;YAAE,OAAO,KAAK,CAAA;QAE1C,IAAI,WAAW,GAAG,IAAI,CAAC,WAAW,CAAA;QAClC,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,WAAW,GAAG,WAAW,CAAC,WAAW,EAAE,CAAA;YACvC,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QAC3B,CAAC;QACD,IAAI,IAAI;YAAE,WAAW,GAAG,WAAW,CAAC,IAAI,EAAE,CAAA;QAE1C,OAAO,WAAW,KAAK,IAAI,CAAA;IAC7B,CAAC,CAAA;AACH,CAAC"}
@@ -1,4 +1,4 @@
1
- import { ITerminalMatcher } from '../types';
1
+ import { ITerminalMatcher } from "../types.js";
2
2
  interface ITextContentIncludesOptions {
3
3
  caseSensitive?: boolean;
4
4
  trim?: boolean;
@@ -0,0 +1,16 @@
1
+ import { isNull } from '@blackglory/prelude';
2
+ export function textContentIncludes(searchString, { caseSensitive = true, trim = false } = {}) {
3
+ return (node) => {
4
+ if (isNull(node.textContent))
5
+ return false;
6
+ let textContent = node.textContent;
7
+ if (!caseSensitive) {
8
+ textContent = textContent.toLowerCase();
9
+ searchString = searchString.toLowerCase();
10
+ }
11
+ if (trim)
12
+ textContent = textContent.trim();
13
+ return textContent.includes(searchString);
14
+ };
15
+ }
16
+ //# sourceMappingURL=text-content-includes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-content-includes.js","sourceRoot":"","sources":["../../src/matchers/text-content-includes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAO5C,MAAM,UAAU,mBAAmB,CACjC,YAAoB,EACpB,EACE,aAAa,GAAG,IAAI,EACpB,IAAI,GAAG,KAAK,KACmB,EAAE;IAEnC,OAAO,CAAC,IAAU,EAAE,EAAE;QACpB,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;YAAE,OAAO,KAAK,CAAA;QAE1C,IAAI,WAAW,GAAG,IAAI,CAAC,WAAW,CAAA;QAClC,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,WAAW,GAAG,WAAW,CAAC,WAAW,EAAE,CAAA;YACvC,YAAY,GAAG,YAAY,CAAC,WAAW,EAAE,CAAA;QAC3C,CAAC;QACD,IAAI,IAAI;YAAE,WAAW,GAAG,WAAW,CAAC,IAAI,EAAE,CAAA;QAE1C,OAAO,WAAW,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAA;IAC3C,CAAC,CAAA;AACH,CAAC"}
@@ -1,4 +1,4 @@
1
- import { ITerminalMatcher } from '../types';
1
+ import { ITerminalMatcher } from "../types.js";
2
2
  interface ITextContentMatchesOptions {
3
3
  trim?: boolean;
4
4
  }
@@ -0,0 +1,12 @@
1
+ import { isNull } from '@blackglory/prelude';
2
+ export function textContentMatches(pattern, { trim = false } = {}) {
3
+ return (node) => {
4
+ if (isNull(node.textContent))
5
+ return false;
6
+ let textContent = node.textContent;
7
+ if (trim)
8
+ textContent = textContent.trim();
9
+ return pattern.test(textContent);
10
+ };
11
+ }
12
+ //# sourceMappingURL=text-content-matches.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-content-matches.js","sourceRoot":"","sources":["../../src/matchers/text-content-matches.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAM5C,MAAM,UAAU,kBAAkB,CAChC,OAAe,EACf,EAAE,IAAI,GAAG,KAAK,KAAiC,EAAE;IAEjD,OAAO,CAAC,IAAU,EAAE,EAAE;QACpB,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;YAAE,OAAO,KAAK,CAAA;QAE1C,IAAI,WAAW,GAAG,IAAI,CAAC,WAAW,CAAA;QAClC,IAAI,IAAI;YAAE,WAAW,GAAG,WAAW,CAAC,IAAI,EAAE,CAAA;QAE1C,OAAO,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IAClC,CAAC,CAAA;AACH,CAAC"}
@@ -1,4 +1,4 @@
1
- import { INestedMatcher, ITerminalMatcher } from '../types';
1
+ import { INestedMatcher, ITerminalMatcher } from "../types.js";
2
2
  export declare function textNode(strings: TemplateStringsArray, ...values: string[]): (...matchers: Array<ITerminalMatcher<Node>>) => INestedMatcher<Node>;
3
3
  export declare function textNode(name: string, ...matchers: Array<ITerminalMatcher<Node>>): INestedMatcher<Node>;
4
4
  export declare function textNode(...matchers: Array<ITerminalMatcher<Node>>): INestedMatcher<Node>;
@@ -0,0 +1,30 @@
1
+ import { isArray, isString } from '@blackglory/prelude';
2
+ import { concat } from "../utils/concat.js";
3
+ import { isntTextNode } from 'extra-dom';
4
+ import { mergeInPlace } from "../utils/merge-in-place.js";
5
+ export function textNode(...args) {
6
+ if (isArray(args[0])) {
7
+ const [strings, ...values] = args;
8
+ const name = concat(strings, values).join('');
9
+ return (...matchers) => textNode(name, ...matchers);
10
+ }
11
+ if (isString(args[0])) {
12
+ const [name, ...matchers] = args;
13
+ return function (node) {
14
+ const result = textNode(...matchers).call(this, node);
15
+ if (result) {
16
+ mergeInPlace(this.collection, { [name]: node });
17
+ }
18
+ return result;
19
+ };
20
+ }
21
+ const [...matchers] = args;
22
+ return function (node) {
23
+ if (isntTextNode(node))
24
+ return false;
25
+ if (matchers.length === 0)
26
+ return true;
27
+ return matchers.every(match => match.call(this, node));
28
+ };
29
+ }
30
+ //# sourceMappingURL=text-node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-node.js","sourceRoot":"","sources":["../../src/matchers/text-node.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,MAAM,EAAE,2BAAwB;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,mCAAgC;AAavD,MAAM,UAAU,QAAQ,CAAC,GAAG,IAGkB;IAE5C,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACrB,MAAM,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,GACxB,IAA4D,CAAA;QAC9D,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAE7C,OAAO,CAAC,GAAG,QAAuC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAA;IACpF,CAAC;IAED,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,GACvB,IAAkE,CAAA;QAEpE,OAAO,UAAkC,IAAU;YACjD,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;YACrD,IAAI,MAAM,EAAE,CAAC;gBACX,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;YACjD,CAAC;YACD,OAAO,MAAM,CAAA;QACf,CAAC,CAAA;IACH,CAAC;IAED,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,IAAoD,CAAA;IAE1E,OAAO,UAAkC,IAAU;QACjD,IAAI,YAAY,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAA;QACpC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA;QAEtC,OAAO,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;IACxD,CAAC,CAAA;AACH,CAAC"}
@@ -1,3 +1,3 @@
1
- import { ITerminalMatcher } from '../types';
1
+ import { ITerminalMatcher } from "../types.js";
2
2
  export declare function xpath(strings: TemplateStringsArray, ...values: string[]): ITerminalMatcher<Node>;
3
3
  export declare function xpath(experssion: string): ITerminalMatcher<Node>;
@@ -1,27 +1,23 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.xpath = void 0;
4
- const types_1 = require("@blackglory/types");
5
- const concat_1 = require("../utils/concat");
6
- const errors_1 = require("@blackglory/errors");
1
+ import { isString } from '@blackglory/prelude';
2
+ import { concat } from "../utils/concat.js";
3
+ import { assert } from '@blackglory/prelude';
7
4
  const UNORDERED_NODE_ITERATOR_TYPE = 'XPathResult' in globalThis
8
5
  ? XPathResult.UNORDERED_NODE_ITERATOR_TYPE
9
6
  : 4;
10
- function xpath(...args) {
11
- if ((0, types_1.isString)(args[0])) {
7
+ export function xpath(...args) {
8
+ if (isString(args[0])) {
12
9
  const [expression] = args;
13
- (0, errors_1.assert)(expression.startsWith('//*'), 'XPath expressions must start with "//*"');
10
+ assert(expression.startsWith('//*'), 'XPath expressions must start with "//*"');
14
11
  return function (node) {
15
12
  return xpathMatches(this.document, expression, node);
16
13
  };
17
14
  }
18
15
  else {
19
16
  const [strings, ...values] = args;
20
- const expression = (0, concat_1.concat)(strings, values).join('');
17
+ const expression = concat(strings, values).join('');
21
18
  return xpath(expression);
22
19
  }
23
20
  }
24
- exports.xpath = xpath;
25
21
  function xpathMatches(document, expression, node) {
26
22
  const iterator = document.evaluate(expression, node, null, UNORDERED_NODE_ITERATOR_TYPE, null);
27
23
  let value;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xpath.js","sourceRoot":"","sources":["../../src/matchers/xpath.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAE,2BAAwB;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAE5C,MAAM,4BAA4B,GAChC,aAAa,IAAI,UAAU;IAC3B,CAAC,CAAC,WAAW,CAAC,4BAA4B;IAC1C,CAAC,CAAC,CAAC,CAAA;AASL,MAAM,UAAU,KAAK,CAAC,GAAG,IAE6B;IAEpD,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,UAAU,CAAC,GAAG,IAAI,CAAA;QACzB,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,yCAAyC,CAAC,CAAA;QAE/E,OAAO,UAEL,IAAU;YAEV,OAAO,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,CAAA;QACtD,CAAC,CAAA;IACH,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,GAAG,IAAI,CAAA;QACjC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAEnD,OAAO,KAAK,CAAC,UAAU,CAAC,CAAA;IAC1B,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,QAAkB,EAAE,UAAkB,EAAE,IAAU;IACtE,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAChC,UAAU,EACV,IAAI,EACJ,IAAI,EACJ,4BAA4B,EAC5B,IAAI,CACL,CAAA;IAED,IAAI,KAAK,CAAA;IACT,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;QACjD,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,IAAI,CAAA;IACjC,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
package/lib/types.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ export interface IContext {
2
+ readonly document: Document;
3
+ readonly next: (node: Node, distance?: number) => Node | undefined;
4
+ readonly collection: {
5
+ [name: string]: Node | Node[];
6
+ };
7
+ }
8
+ export interface IReadonlyContext {
9
+ readonly document: Document;
10
+ readonly next: (node: Node, distance?: number) => Node | undefined;
11
+ readonly collection: {
12
+ readonly [name: string]: Node | Node[];
13
+ };
14
+ }
15
+ export type IMatcher<T extends Node> = ITerminalMatcher<T> | INestedMatcher<T> | ISkipMatcher<T> | (<T extends Node>(this: IReadonlyContext, node: T) => boolean | number | Iterable<number>);
16
+ export type INestedMatcher<T extends Node> = (this: IReadonlyContext, node: T) => boolean;
17
+ export type ISkipMatcher<T extends Node> = (this: IReadonlyContext, node: T) => number | Iterable<number> | false;
18
+ export type ITerminalMatcher<T extends Node> = (this: IReadonlyContext, node: T) => boolean;
package/lib/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.concat = void 0;
4
- function concat(strings, values) {
1
+ export function concat(strings, values) {
5
2
  const result = [];
6
3
  for (let i = 0, len = values.length; i < len; i++) {
7
4
  result.push(strings[i]);
@@ -10,5 +7,4 @@ function concat(strings, values) {
10
7
  result.push(strings[strings.length - 1]);
11
8
  return result;
12
9
  }
13
- exports.concat = concat;
14
10
  //# sourceMappingURL=concat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concat.js","sourceRoot":"","sources":["../../src/utils/concat.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,MAAM,CAAC,OAA6B,EAAE,MAAgB;IACpE,MAAM,MAAM,GAAG,EAAE,CAAA;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;QACvB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;IACxB,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;IACxC,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -1,2 +1,5 @@
1
- import { INestedMatcher, ITerminalMatcher, IReadonlyContext } from '../types';
1
+ import { INestedMatcher, ITerminalMatcher, IReadonlyContext } from "../types.js";
2
+ /**
3
+ * @returns {number} 返回值为成功匹配的元素个数, 当此值等于ubound时, 代表匹配成功.
4
+ */
2
5
  export declare function matchMultiple<T extends Node>(this: IReadonlyContext, node: T, ubound: number, matcher: INestedMatcher<T> | ITerminalMatcher<T>): number;
@@ -0,0 +1,20 @@
1
+ import { countup } from 'extra-generator';
2
+ /**
3
+ * @returns {number} 返回值为成功匹配的元素个数, 当此值等于ubound时, 代表匹配成功.
4
+ */
5
+ export function matchMultiple(node, ubound, matcher) {
6
+ let currentNode = node;
7
+ for (const round of countup(1, ubound)) {
8
+ if (!currentNode)
9
+ return round - 1;
10
+ const result = matcher.call(this, currentNode);
11
+ if (result) {
12
+ currentNode = this.next(currentNode);
13
+ }
14
+ else {
15
+ return round - 1;
16
+ }
17
+ }
18
+ return ubound;
19
+ }
20
+ //# sourceMappingURL=match-multiple.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match-multiple.js","sourceRoot":"","sources":["../../src/utils/match-multiple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAGzC;;GAEG;AACH,MAAM,UAAU,aAAa,CAE3B,IAAO,EACP,MAAc,EACd,OAAgD;IAEhD,IAAI,WAAW,GAAa,IAAI,CAAA;IAEhC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC,WAAW;YAAE,OAAO,KAAK,GAAG,CAAC,CAAA;QAElC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;QAC9C,IAAI,MAAM,EAAE,CAAC;YACX,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAa,CAAA;QAClD,CAAC;aAAM,CAAC;YACN,OAAO,KAAK,GAAG,CAAC,CAAA;QAClB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -1,2 +1,2 @@
1
- import { IMatcher, IReadonlyContext } from '../types';
1
+ import { IMatcher, IReadonlyContext } from "../types.js";
2
2
  export declare function matchOneByOne<T extends Node>(context: IReadonlyContext, source: T | null, ...matchers: Array<IMatcher<T>>): boolean;
@@ -1,15 +1,13 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.matchOneByOne = void 0;
4
- const types_1 = require("@blackglory/types");
5
- function matchOneByOne(context, source, ...matchers) {
1
+ import { isBoolean, isNumber, isIterable } from '@blackglory/prelude';
2
+ export function matchOneByOne(context, source, ...matchers) {
6
3
  if (matchers.length === 0)
7
4
  return true;
8
5
  if (!source)
9
6
  return false;
10
7
  const [matcher, ...otherMatchers] = matchers;
11
8
  const result = Reflect.apply(matcher, context, [source]);
12
- if ((0, types_1.isBoolean)(result)) {
9
+ // TerminalMatcher
10
+ if (isBoolean(result)) {
13
11
  if (result) {
14
12
  const nextNode = context.next(source);
15
13
  return matchOneByOne(context, nextNode, ...otherMatchers);
@@ -18,21 +16,23 @@ function matchOneByOne(context, source, ...matchers) {
18
16
  return false;
19
17
  }
20
18
  }
21
- if ((0, types_1.isNumber)(result)) {
19
+ // 此处一定是成功匹配, 因为SkipMatcher在失败时会返回false.
20
+ if (isNumber(result)) {
22
21
  const distance = result;
23
22
  const nextNode = context.next(source, distance);
24
23
  return matchOneByOne(context, nextNode, ...otherMatchers);
25
24
  }
26
- if ((0, types_1.isIterable)(result)) {
25
+ // SkipMatcher返回Iterable意味着存在多种可能性, 可能出现失败回溯.
26
+ if (isIterable(result)) {
27
27
  for (const distance of result) {
28
28
  const nextNode = context.next(source, distance);
29
29
  if (matchOneByOne(context, nextNode, ...otherMatchers)) {
30
30
  return true;
31
31
  }
32
32
  }
33
+ // 尝试了所有可能性, 未发现可以匹配的结果
33
34
  return false;
34
35
  }
35
36
  throw new Error('Unknown return value');
36
37
  }
37
- exports.matchOneByOne = matchOneByOne;
38
38
  //# sourceMappingURL=match-one-by-one.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match-one-by-one.js","sourceRoot":"","sources":["../../src/utils/match-one-by-one.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAErE,MAAM,UAAU,aAAa,CAC3B,OAAyB,EACzB,MAAgB,EAChB,GAAG,QAA4B;IAE/B,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACtC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IAEzB,MAAM,CAAC,OAAO,EAAE,GAAG,aAAa,CAAC,GAAG,QAAQ,CAAA;IAE5C,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,CAA+B,CAAA;IAEtF,kBAAkB;IAClB,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAa,CAAA;YACjD,OAAO,aAAa,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,CAAA;QAC3D,CAAC;aAAM,CAAC;YACN,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,MAAM,CAAA;QACvB,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAa,CAAA;QAC3D,OAAO,aAAa,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,CAAA;IAC3D,CAAC;IAED,6CAA6C;IAC7C,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,KAAK,MAAM,QAAQ,IAAI,MAAM,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAa,CAAA;YAC3D,IAAI,aAAa,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,EAAE,CAAC;gBACvD,OAAO,IAAI,CAAA;YACb,CAAC;QACH,CAAC;QAED,uBAAuB;QACvB,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAA;AACzC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function mergeInPlace<T>(target: Record<string, T | T[]>, source: Record<string, T | T[]>): void;
@@ -1,12 +1,9 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mergeInPlace = void 0;
4
- const types_1 = require("@blackglory/types");
5
- function mergeInPlace(target, source) {
1
+ import { isArray } from '@blackglory/prelude';
2
+ export function mergeInPlace(target, source) {
6
3
  for (const [key, value] of Object.entries(source)) {
7
4
  if (target[key]) {
8
- if ((0, types_1.isArray)(target[key])) {
9
- if ((0, types_1.isArray)(value)) {
5
+ if (isArray(target[key])) {
6
+ if (isArray(value)) {
10
7
  target[key] = [...target[key], ...value];
11
8
  }
12
9
  else {
@@ -14,7 +11,7 @@ function mergeInPlace(target, source) {
14
11
  }
15
12
  }
16
13
  else {
17
- if ((0, types_1.isArray)(value)) {
14
+ if (isArray(value)) {
18
15
  target[key] = [target[key], ...value];
19
16
  }
20
17
  else {
@@ -27,5 +24,4 @@ function mergeInPlace(target, source) {
27
24
  }
28
25
  }
29
26
  }
30
- exports.mergeInPlace = mergeInPlace;
31
27
  //# sourceMappingURL=merge-in-place.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-in-place.js","sourceRoot":"","sources":["../../src/utils/merge-in-place.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAE7C,MAAM,UAAU,YAAY,CAC1B,MAA+B,EAC/B,MAA+B;IAE/B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAChB,IAAI,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBACzB,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBACnB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAQ,EAAE,GAAG,KAAK,CAAC,CAAA;gBACjD,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAQ,EAAE,KAAK,CAAC,CAAA;gBAC9C,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBACnB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAM,EAAE,GAAG,KAAK,CAAC,CAAA;gBAC5C,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAM,EAAE,KAAK,CAAC,CAAA;gBACzC,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;QACrB,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ import * as ExtraDOM from 'extra-dom';
2
+ export function nextElementSibling(node, distance = 1) {
3
+ if (distance === 0)
4
+ return node;
5
+ return ExtraDOM.nextElementSibling(node, distance);
6
+ }
7
+ //# sourceMappingURL=next-element-sibling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-element-sibling.js","sourceRoot":"","sources":["../../src/utils/next-element-sibling.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,WAAW,CAAA;AAErC,MAAM,UAAU,kBAAkB,CAChC,IAAU,EACV,WAAmB,CAAC;IAEpB,IAAI,QAAQ,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAE/B,OAAO,QAAQ,CAAC,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;AACpD,CAAC"}
@@ -0,0 +1,7 @@
1
+ import * as ExtraDOM from 'extra-dom';
2
+ export function nextSibling(node, distance = 1) {
3
+ if (distance === 0)
4
+ return node;
5
+ return ExtraDOM.nextSibling(node, distance);
6
+ }
7
+ //# sourceMappingURL=next-sibling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-sibling.js","sourceRoot":"","sources":["../../src/utils/next-sibling.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,WAAW,CAAA;AAErC,MAAM,UAAU,WAAW,CAAC,IAAU,EAAE,WAAmB,CAAC;IAC1D,IAAI,QAAQ,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAE/B,OAAO,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;AAC7C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blackglory/match",
3
- "version": "0.3.5",
3
+ "version": "0.4.0",
4
4
  "description": "A module for matching nodes from pages",
5
5
  "keywords": [
6
6
  "query",
@@ -9,71 +9,56 @@
9
9
  ],
10
10
  "files": [
11
11
  "lib",
12
- "dist"
12
+ "src"
13
13
  ],
14
- "main": "lib/es2018/index.js",
15
- "types": "lib/es2018/index.d.ts",
14
+ "type": "module",
15
+ "main": "lib/index.js",
16
+ "types": "lib/index.d.ts",
17
+ "sideEffects": false,
18
+ "engines": {
19
+ "node": ">=22"
20
+ },
16
21
  "repository": "git@github.com:BlackGlory/match.git",
17
22
  "author": "BlackGlory <woshenmedoubuzhidao@blackglory.me>",
18
23
  "license": "MIT",
19
- "sideEffects": false,
20
24
  "scripts": {
25
+ "prepare": "ts-patch install -s",
21
26
  "lint": "eslint --ext .js,.jsx,.ts,.tsx --quiet src __tests__",
22
- "test": "jest --config jest.config.js",
23
- "test:coverage": "jest --coverage --config jest.config.js",
24
- "prepublishOnly": "run-s clean build bundle",
25
- "clean": "run-p clean:*",
26
- "clean:build": "rimraf lib",
27
- "clean:bundle": "rimraf dist",
28
- "build": "run-p build:*",
29
- "build:es2015": "run-s build:es2015:*",
30
- "build:es2015:compile": "tsc --project tsconfig.build.json --module commonjs --target es2015 --outDir lib/es2015",
31
- "build:es2015:patch": "tscpaths -p tsconfig.build.json -s ./src -o ./lib/es2015",
32
- "build:es2018": "run-s build:es2018:*",
33
- "build:es2018:compile": "tsc --project tsconfig.build.json --module commonjs --target es2018 --outDir lib/es2018",
34
- "build:es2018:patch": "tscpaths -p tsconfig.build.json -s ./src -o ./lib/es2018",
35
- "bundle": "rollup --config rollup.config.js",
27
+ "test": "vitest --run",
28
+ "prepublishOnly": "run-s prepare clean build",
29
+ "clean": "rimraf lib",
30
+ "build": "tsc --project tsconfig.build.json",
36
31
  "release": "standard-version"
37
32
  },
38
33
  "husky": {
39
34
  "hooks": {
40
- "pre-commit": "run-s lint build test",
35
+ "pre-commit": "run-s prepare lint build test",
41
36
  "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
42
37
  }
43
38
  },
44
39
  "devDependencies": {
45
- "@blackglory/jest-matchers": "^0.2.1",
46
- "@commitlint/cli": "^15.0.0",
47
- "@commitlint/config-conventional": "^15.0.0",
48
- "@rollup/plugin-commonjs": "^21.0.1",
49
- "@rollup/plugin-json": "^4.1.0",
50
- "@rollup/plugin-node-resolve": "^13.0.6",
51
- "@rollup/plugin-replace": "^3.0.0",
52
- "@rollup/plugin-typescript": "^8.3.0",
53
- "@types/jest": "^27.0.3",
54
- "@types/jsdom": "^16.2.13",
55
- "@typescript-eslint/eslint-plugin": "^5.6.0",
56
- "@typescript-eslint/parser": "^5.6.0",
57
- "eslint": "^8.4.1",
40
+ "@commitlint/cli": "^20.3.1",
41
+ "@commitlint/config-conventional": "^20.3.1",
42
+ "@eslint/js": "^9.39.2",
43
+ "@types/jsdom": "^27.0.0",
44
+ "eslint": "^9.39.2",
58
45
  "husky": "^4.3.8",
59
- "iterable-operator": "^0.14.4",
60
- "jest": "^27.4.4",
61
- "jsdom": "^19.0.0",
46
+ "iterable-operator": "^5.1.0",
47
+ "jsdom": "^27.4.0",
62
48
  "npm-run-all": "^4.1.5",
63
- "rimraf": "^3.0.2",
64
- "rollup": "^2.61.1",
65
- "rollup-plugin-analyzer": "^4.0.0",
66
- "rollup-plugin-terser": "^7.0.2",
67
- "standard-version": "^9.3.2",
68
- "ts-jest": "^27.1.1",
69
- "tscpaths": "^0.0.9",
70
- "tslib": "^2.3.1",
71
- "typescript": "^4.5.3"
49
+ "rimraf": "^6.1.2",
50
+ "standard-version": "^9.5.0",
51
+ "ts-patch": "^3.3.0",
52
+ "tslib": "^2.8.1",
53
+ "typescript": "^5.9.3",
54
+ "typescript-eslint": "^8.53.0",
55
+ "typescript-transform-paths": "^3.5.6",
56
+ "vite-tsconfig-paths": "^6.0.4",
57
+ "vitest": "^4.0.17"
72
58
  },
73
59
  "dependencies": {
74
- "@blackglory/errors": "^1.1.2",
75
- "@blackglory/types": "^0.5.2",
76
- "extra-dom": "^0.4.4",
77
- "extra-generator": "^0.2.15"
60
+ "@blackglory/prelude": "^0.4.0",
61
+ "extra-dom": "^0.7.0",
62
+ "extra-generator": "^0.5.9"
78
63
  }
79
64
  }
package/src/index.ts ADDED
@@ -0,0 +1,18 @@
1
+ export { match } from './match.js'
2
+ export { matchElement } from './match-element.js'
3
+
4
+ export { anyOf } from '@matchers/any-of.js'
5
+ export { childNodes } from '@matchers/child-nodes.js'
6
+ export { children } from '@matchers/children.js'
7
+ export { css } from '@matchers/css.js'
8
+ export { element } from '@matchers/element.js'
9
+ export { multiple } from '@matchers/multiple.js'
10
+ export { node } from '@matchers/node.js'
11
+ export { optional } from '@matchers/optional.js'
12
+ export { repeat } from '@matchers/repeat.js'
13
+ export { tap } from '@matchers/tap.js'
14
+ export { textContentEquals } from '@matchers/text-content-equals.js'
15
+ export { textContentIncludes } from '@matchers/text-content-includes.js'
16
+ export { textContentMatches } from '@matchers/text-content-matches.js'
17
+ export { textNode } from '@matchers/text-node.js'
18
+ export { xpath } from '@matchers/xpath.js'
@@ -0,0 +1,23 @@
1
+ import { isDocument } from 'extra-dom'
2
+ import { IMatcher, IContext } from './types.js'
3
+ import { matchOneByOne } from '@utils/match-one-by-one.js'
4
+ import { nextElementSibling } from '@utils/next-element-sibling.js'
5
+
6
+ export function matchElement(
7
+ this: void | Document
8
+ , element: Element
9
+ , ...matchers: Array<IMatcher<Element>>
10
+ ): { [name: string]: Node | Node[] } | null {
11
+ const document = isDocument(this) ? this : globalThis.document
12
+ const context: IContext = {
13
+ document
14
+ , collection: {}
15
+ , next: nextElementSibling
16
+ }
17
+
18
+ if (matchOneByOne(context, element, ...matchers)) {
19
+ return context.collection
20
+ } else {
21
+ return null
22
+ }
23
+ }
package/src/match.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { isDocument } from 'extra-dom'
2
+ import { IMatcher, IContext } from './types.js'
3
+ import { matchOneByOne } from '@utils/match-one-by-one.js'
4
+ import { nextSibling } from '@utils/next-sibling.js'
5
+
6
+ export function match(
7
+ this: void | Document
8
+ , node: Node
9
+ , ...matchers: Array<IMatcher<Node>>
10
+ ): { [name: string]: Node | Node[] } | null {
11
+ const document = isDocument(this) ? this : globalThis.document
12
+ const context: IContext = {
13
+ document
14
+ , collection: {}
15
+ , next: nextSibling
16
+ }
17
+
18
+ if (matchOneByOne(context, node, ...matchers)) {
19
+ return context.collection
20
+ } else {
21
+ return null
22
+ }
23
+ }
@@ -0,0 +1,13 @@
1
+ import { ITerminalMatcher, INestedMatcher, IReadonlyContext } from '@src/types.js'
2
+
3
+ export function anyOf<T extends Node>(
4
+ ...matchers: [
5
+ INestedMatcher<T> | ITerminalMatcher<T>
6
+ , INestedMatcher<T> | ITerminalMatcher<T>
7
+ , ...Array<INestedMatcher<T> | ITerminalMatcher<T>>
8
+ ]
9
+ ): INestedMatcher<T> {
10
+ return function (this: IReadonlyContext, node: T) {
11
+ return matchers.some(match => match.call(this, node))
12
+ }
13
+ }
@@ -0,0 +1,33 @@
1
+ import { INestedMatcher, IMatcher, IReadonlyContext } from '@src/types.js'
2
+ import { matchOneByOne } from '@utils/match-one-by-one.js'
3
+ import { mergeInPlace } from '@utils/merge-in-place.js'
4
+ import { nextSibling } from '@utils/next-sibling.js'
5
+
6
+ export function childNodes(...matchers: Array<IMatcher<Node>>): INestedMatcher<Node> {
7
+ return function (this: IReadonlyContext, node: Node) {
8
+ // 空matchers意味着"childNodes应该为空".
9
+ if (matchers.length === 0) {
10
+ return node.childNodes.length === 0
11
+ }
12
+
13
+ if (node.childNodes.length === 0) return false
14
+
15
+ const context: IReadonlyContext = {
16
+ ...this
17
+ , collection: {}
18
+ , next: nextSibling
19
+ }
20
+
21
+ const result = matchOneByOne(
22
+ context
23
+ , node.childNodes[0]
24
+ , ...matchers
25
+ )
26
+
27
+ if (result) {
28
+ mergeInPlace(this.collection, context.collection)
29
+ }
30
+
31
+ return result
32
+ }
33
+ }
@@ -0,0 +1,35 @@
1
+ import { IMatcher, INestedMatcher, IReadonlyContext } from '@src/types.js'
2
+ import { matchOneByOne } from '@utils/match-one-by-one.js'
3
+ import { mergeInPlace } from '@utils/merge-in-place.js'
4
+ import { nextElementSibling } from '@utils/next-element-sibling.js'
5
+
6
+ export function children(
7
+ ...matchers: Array<IMatcher<Element>>
8
+ ): INestedMatcher<Element> {
9
+ return function (this: IReadonlyContext, element: Element) {
10
+ // 空matchers意味着"children应该为空".
11
+ if (matchers.length === 0) {
12
+ return element.children.length === 0
13
+ }
14
+
15
+ if (element.children.length === 0) return false
16
+
17
+ const context: IReadonlyContext = {
18
+ ...this
19
+ , collection: {}
20
+ , next: nextElementSibling
21
+ }
22
+
23
+ const result = matchOneByOne(
24
+ context
25
+ , element.children[0]
26
+ , ...matchers
27
+ )
28
+
29
+ if (result) {
30
+ mergeInPlace(this.collection, context.collection)
31
+ }
32
+
33
+ return result
34
+ }
35
+ }