You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			222 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			JavaScript
		
	
			
		
		
	
	
			222 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			JavaScript
		
	
| import boolbase from "boolbase";
 | |
| /**
 | |
|  * All reserved characters in a regex, used for escaping.
 | |
|  *
 | |
|  * Taken from XRegExp, (c) 2007-2020 Steven Levithan under the MIT license
 | |
|  * https://github.com/slevithan/xregexp/blob/95eeebeb8fac8754d54eafe2b4743661ac1cf028/src/xregexp.js#L794
 | |
|  */
 | |
| const reChars = /[-[\]{}()*+?.,\\^$|#\s]/g;
 | |
| function escapeRegex(value) {
 | |
|     return value.replace(reChars, "\\$&");
 | |
| }
 | |
| /**
 | |
|  * Attributes that are case-insensitive in HTML.
 | |
|  *
 | |
|  * @private
 | |
|  * @see https://html.spec.whatwg.org/multipage/semantics-other.html#case-sensitivity-of-selectors
 | |
|  */
 | |
| const caseInsensitiveAttributes = new Set([
 | |
|     "accept",
 | |
|     "accept-charset",
 | |
|     "align",
 | |
|     "alink",
 | |
|     "axis",
 | |
|     "bgcolor",
 | |
|     "charset",
 | |
|     "checked",
 | |
|     "clear",
 | |
|     "codetype",
 | |
|     "color",
 | |
|     "compact",
 | |
|     "declare",
 | |
|     "defer",
 | |
|     "dir",
 | |
|     "direction",
 | |
|     "disabled",
 | |
|     "enctype",
 | |
|     "face",
 | |
|     "frame",
 | |
|     "hreflang",
 | |
|     "http-equiv",
 | |
|     "lang",
 | |
|     "language",
 | |
|     "link",
 | |
|     "media",
 | |
|     "method",
 | |
|     "multiple",
 | |
|     "nohref",
 | |
|     "noresize",
 | |
|     "noshade",
 | |
|     "nowrap",
 | |
|     "readonly",
 | |
|     "rel",
 | |
|     "rev",
 | |
|     "rules",
 | |
|     "scope",
 | |
|     "scrolling",
 | |
|     "selected",
 | |
|     "shape",
 | |
|     "target",
 | |
|     "text",
 | |
|     "type",
 | |
|     "valign",
 | |
|     "valuetype",
 | |
|     "vlink",
 | |
| ]);
 | |
| function shouldIgnoreCase(selector, options) {
 | |
|     return typeof selector.ignoreCase === "boolean"
 | |
|         ? selector.ignoreCase
 | |
|         : selector.ignoreCase === "quirks"
 | |
|             ? !!options.quirksMode
 | |
|             : !options.xmlMode && caseInsensitiveAttributes.has(selector.name);
 | |
| }
 | |
| /**
 | |
|  * Attribute selectors
 | |
|  */
 | |
| export const attributeRules = {
 | |
|     equals(next, data, options) {
 | |
|         const { adapter } = options;
 | |
|         const { name } = data;
 | |
|         let { value } = data;
 | |
|         if (shouldIgnoreCase(data, options)) {
 | |
|             value = value.toLowerCase();
 | |
|             return (elem) => {
 | |
|                 const attr = adapter.getAttributeValue(elem, name);
 | |
|                 return (attr != null &&
 | |
|                     attr.length === value.length &&
 | |
|                     attr.toLowerCase() === value &&
 | |
|                     next(elem));
 | |
|             };
 | |
|         }
 | |
|         return (elem) => adapter.getAttributeValue(elem, name) === value && next(elem);
 | |
|     },
 | |
|     hyphen(next, data, options) {
 | |
|         const { adapter } = options;
 | |
|         const { name } = data;
 | |
|         let { value } = data;
 | |
|         const len = value.length;
 | |
|         if (shouldIgnoreCase(data, options)) {
 | |
|             value = value.toLowerCase();
 | |
|             return function hyphenIC(elem) {
 | |
|                 const attr = adapter.getAttributeValue(elem, name);
 | |
|                 return (attr != null &&
 | |
|                     (attr.length === len || attr.charAt(len) === "-") &&
 | |
|                     attr.substr(0, len).toLowerCase() === value &&
 | |
|                     next(elem));
 | |
|             };
 | |
|         }
 | |
|         return function hyphen(elem) {
 | |
|             const attr = adapter.getAttributeValue(elem, name);
 | |
|             return (attr != null &&
 | |
|                 (attr.length === len || attr.charAt(len) === "-") &&
 | |
|                 attr.substr(0, len) === value &&
 | |
|                 next(elem));
 | |
|         };
 | |
|     },
 | |
|     element(next, data, options) {
 | |
|         const { adapter } = options;
 | |
|         const { name, value } = data;
 | |
|         if (/\s/.test(value)) {
 | |
|             return boolbase.falseFunc;
 | |
|         }
 | |
|         const regex = new RegExp(`(?:^|\\s)${escapeRegex(value)}(?:$|\\s)`, shouldIgnoreCase(data, options) ? "i" : "");
 | |
|         return function element(elem) {
 | |
|             const attr = adapter.getAttributeValue(elem, name);
 | |
|             return (attr != null &&
 | |
|                 attr.length >= value.length &&
 | |
|                 regex.test(attr) &&
 | |
|                 next(elem));
 | |
|         };
 | |
|     },
 | |
|     exists(next, { name }, { adapter }) {
 | |
|         return (elem) => adapter.hasAttrib(elem, name) && next(elem);
 | |
|     },
 | |
|     start(next, data, options) {
 | |
|         const { adapter } = options;
 | |
|         const { name } = data;
 | |
|         let { value } = data;
 | |
|         const len = value.length;
 | |
|         if (len === 0) {
 | |
|             return boolbase.falseFunc;
 | |
|         }
 | |
|         if (shouldIgnoreCase(data, options)) {
 | |
|             value = value.toLowerCase();
 | |
|             return (elem) => {
 | |
|                 const attr = adapter.getAttributeValue(elem, name);
 | |
|                 return (attr != null &&
 | |
|                     attr.length >= len &&
 | |
|                     attr.substr(0, len).toLowerCase() === value &&
 | |
|                     next(elem));
 | |
|             };
 | |
|         }
 | |
|         return (elem) => {
 | |
|             var _a;
 | |
|             return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.startsWith(value)) &&
 | |
|                 next(elem);
 | |
|         };
 | |
|     },
 | |
|     end(next, data, options) {
 | |
|         const { adapter } = options;
 | |
|         const { name } = data;
 | |
|         let { value } = data;
 | |
|         const len = -value.length;
 | |
|         if (len === 0) {
 | |
|             return boolbase.falseFunc;
 | |
|         }
 | |
|         if (shouldIgnoreCase(data, options)) {
 | |
|             value = value.toLowerCase();
 | |
|             return (elem) => {
 | |
|                 var _a;
 | |
|                 return ((_a = adapter
 | |
|                     .getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.substr(len).toLowerCase()) === value && next(elem);
 | |
|             };
 | |
|         }
 | |
|         return (elem) => {
 | |
|             var _a;
 | |
|             return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.endsWith(value)) &&
 | |
|                 next(elem);
 | |
|         };
 | |
|     },
 | |
|     any(next, data, options) {
 | |
|         const { adapter } = options;
 | |
|         const { name, value } = data;
 | |
|         if (value === "") {
 | |
|             return boolbase.falseFunc;
 | |
|         }
 | |
|         if (shouldIgnoreCase(data, options)) {
 | |
|             const regex = new RegExp(escapeRegex(value), "i");
 | |
|             return function anyIC(elem) {
 | |
|                 const attr = adapter.getAttributeValue(elem, name);
 | |
|                 return (attr != null &&
 | |
|                     attr.length >= value.length &&
 | |
|                     regex.test(attr) &&
 | |
|                     next(elem));
 | |
|             };
 | |
|         }
 | |
|         return (elem) => {
 | |
|             var _a;
 | |
|             return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.includes(value)) &&
 | |
|                 next(elem);
 | |
|         };
 | |
|     },
 | |
|     not(next, data, options) {
 | |
|         const { adapter } = options;
 | |
|         const { name } = data;
 | |
|         let { value } = data;
 | |
|         if (value === "") {
 | |
|             return (elem) => !!adapter.getAttributeValue(elem, name) && next(elem);
 | |
|         }
 | |
|         else if (shouldIgnoreCase(data, options)) {
 | |
|             value = value.toLowerCase();
 | |
|             return (elem) => {
 | |
|                 const attr = adapter.getAttributeValue(elem, name);
 | |
|                 return ((attr == null ||
 | |
|                     attr.length !== value.length ||
 | |
|                     attr.toLowerCase() !== value) &&
 | |
|                     next(elem));
 | |
|             };
 | |
|         }
 | |
|         return (elem) => adapter.getAttributeValue(elem, name) !== value && next(elem);
 | |
|     },
 | |
| };
 | |
| //# sourceMappingURL=attributes.js.map
 |