attributes.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.attributeRules = void 0;
  4. var boolbase_1 = require("boolbase");
  5. /**
  6. * All reserved characters in a regex, used for escaping.
  7. *
  8. * Taken from XRegExp, (c) 2007-2020 Steven Levithan under the MIT license
  9. * https://github.com/slevithan/xregexp/blob/95eeebeb8fac8754d54eafe2b4743661ac1cf028/src/xregexp.js#L794
  10. */
  11. var reChars = /[-[\]{}()*+?.,\\^$|#\s]/g;
  12. function escapeRegex(value) {
  13. return value.replace(reChars, "\\$&");
  14. }
  15. /**
  16. * Attributes that are case-insensitive in HTML.
  17. *
  18. * @private
  19. * @see https://html.spec.whatwg.org/multipage/semantics-other.html#case-sensitivity-of-selectors
  20. */
  21. var caseInsensitiveAttributes = new Set([
  22. "accept",
  23. "accept-charset",
  24. "align",
  25. "alink",
  26. "axis",
  27. "bgcolor",
  28. "charset",
  29. "checked",
  30. "clear",
  31. "codetype",
  32. "color",
  33. "compact",
  34. "declare",
  35. "defer",
  36. "dir",
  37. "direction",
  38. "disabled",
  39. "enctype",
  40. "face",
  41. "frame",
  42. "hreflang",
  43. "http-equiv",
  44. "lang",
  45. "language",
  46. "link",
  47. "media",
  48. "method",
  49. "multiple",
  50. "nohref",
  51. "noresize",
  52. "noshade",
  53. "nowrap",
  54. "readonly",
  55. "rel",
  56. "rev",
  57. "rules",
  58. "scope",
  59. "scrolling",
  60. "selected",
  61. "shape",
  62. "target",
  63. "text",
  64. "type",
  65. "valign",
  66. "valuetype",
  67. "vlink",
  68. ]);
  69. function shouldIgnoreCase(selector, options) {
  70. return typeof selector.ignoreCase === "boolean"
  71. ? selector.ignoreCase
  72. : selector.ignoreCase === "quirks"
  73. ? !!options.quirksMode
  74. : !options.xmlMode && caseInsensitiveAttributes.has(selector.name);
  75. }
  76. /**
  77. * Attribute selectors
  78. */
  79. exports.attributeRules = {
  80. equals: function (next, data, options) {
  81. var adapter = options.adapter;
  82. var name = data.name;
  83. var value = data.value;
  84. if (shouldIgnoreCase(data, options)) {
  85. value = value.toLowerCase();
  86. return function (elem) {
  87. var attr = adapter.getAttributeValue(elem, name);
  88. return (attr != null &&
  89. attr.length === value.length &&
  90. attr.toLowerCase() === value &&
  91. next(elem));
  92. };
  93. }
  94. return function (elem) {
  95. return adapter.getAttributeValue(elem, name) === value && next(elem);
  96. };
  97. },
  98. hyphen: function (next, data, options) {
  99. var adapter = options.adapter;
  100. var name = data.name;
  101. var value = data.value;
  102. var len = value.length;
  103. if (shouldIgnoreCase(data, options)) {
  104. value = value.toLowerCase();
  105. return function hyphenIC(elem) {
  106. var attr = adapter.getAttributeValue(elem, name);
  107. return (attr != null &&
  108. (attr.length === len || attr.charAt(len) === "-") &&
  109. attr.substr(0, len).toLowerCase() === value &&
  110. next(elem));
  111. };
  112. }
  113. return function hyphen(elem) {
  114. var attr = adapter.getAttributeValue(elem, name);
  115. return (attr != null &&
  116. (attr.length === len || attr.charAt(len) === "-") &&
  117. attr.substr(0, len) === value &&
  118. next(elem));
  119. };
  120. },
  121. element: function (next, data, options) {
  122. var adapter = options.adapter;
  123. var name = data.name, value = data.value;
  124. if (/\s/.test(value)) {
  125. return boolbase_1.falseFunc;
  126. }
  127. var regex = new RegExp("(?:^|\\s)".concat(escapeRegex(value), "(?:$|\\s)"), shouldIgnoreCase(data, options) ? "i" : "");
  128. return function element(elem) {
  129. var attr = adapter.getAttributeValue(elem, name);
  130. return (attr != null &&
  131. attr.length >= value.length &&
  132. regex.test(attr) &&
  133. next(elem));
  134. };
  135. },
  136. exists: function (next, _a, _b) {
  137. var name = _a.name;
  138. var adapter = _b.adapter;
  139. return function (elem) { return adapter.hasAttrib(elem, name) && next(elem); };
  140. },
  141. start: function (next, data, options) {
  142. var adapter = options.adapter;
  143. var name = data.name;
  144. var value = data.value;
  145. var len = value.length;
  146. if (len === 0) {
  147. return boolbase_1.falseFunc;
  148. }
  149. if (shouldIgnoreCase(data, options)) {
  150. value = value.toLowerCase();
  151. return function (elem) {
  152. var attr = adapter.getAttributeValue(elem, name);
  153. return (attr != null &&
  154. attr.length >= len &&
  155. attr.substr(0, len).toLowerCase() === value &&
  156. next(elem));
  157. };
  158. }
  159. return function (elem) {
  160. var _a;
  161. return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.startsWith(value)) &&
  162. next(elem);
  163. };
  164. },
  165. end: function (next, data, options) {
  166. var adapter = options.adapter;
  167. var name = data.name;
  168. var value = data.value;
  169. var len = -value.length;
  170. if (len === 0) {
  171. return boolbase_1.falseFunc;
  172. }
  173. if (shouldIgnoreCase(data, options)) {
  174. value = value.toLowerCase();
  175. return function (elem) {
  176. var _a;
  177. return ((_a = adapter
  178. .getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.substr(len).toLowerCase()) === value && next(elem);
  179. };
  180. }
  181. return function (elem) {
  182. var _a;
  183. return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.endsWith(value)) &&
  184. next(elem);
  185. };
  186. },
  187. any: function (next, data, options) {
  188. var adapter = options.adapter;
  189. var name = data.name, value = data.value;
  190. if (value === "") {
  191. return boolbase_1.falseFunc;
  192. }
  193. if (shouldIgnoreCase(data, options)) {
  194. var regex_1 = new RegExp(escapeRegex(value), "i");
  195. return function anyIC(elem) {
  196. var attr = adapter.getAttributeValue(elem, name);
  197. return (attr != null &&
  198. attr.length >= value.length &&
  199. regex_1.test(attr) &&
  200. next(elem));
  201. };
  202. }
  203. return function (elem) {
  204. var _a;
  205. return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.includes(value)) &&
  206. next(elem);
  207. };
  208. },
  209. not: function (next, data, options) {
  210. var adapter = options.adapter;
  211. var name = data.name;
  212. var value = data.value;
  213. if (value === "") {
  214. return function (elem) {
  215. return !!adapter.getAttributeValue(elem, name) && next(elem);
  216. };
  217. }
  218. else if (shouldIgnoreCase(data, options)) {
  219. value = value.toLowerCase();
  220. return function (elem) {
  221. var attr = adapter.getAttributeValue(elem, name);
  222. return ((attr == null ||
  223. attr.length !== value.length ||
  224. attr.toLowerCase() !== value) &&
  225. next(elem));
  226. };
  227. }
  228. return function (elem) {
  229. return adapter.getAttributeValue(elem, name) !== value && next(elem);
  230. };
  231. },
  232. };