You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							190 lines
						
					
					
						
							5.8 KiB
						
					
					
				
			
		
		
	
	
							190 lines
						
					
					
						
							5.8 KiB
						
					
					
				var falseFunc = require("boolbase").falseFunc; | 
						|
 | 
						|
//https://github.com/slevithan/XRegExp/blob/master/src/xregexp.js#L469 | 
						|
var reChars = /[-[\]{}()*+?.,\\^$|#\s]/g; | 
						|
 | 
						|
/* | 
						|
	attribute selectors | 
						|
*/ | 
						|
var attributeRules = { | 
						|
    __proto__: null, | 
						|
    equals: function(next, data, options) { | 
						|
        var name = data.name; | 
						|
        var value = data.value; | 
						|
        var adapter = options.adapter; | 
						|
 | 
						|
        if (data.ignoreCase) { | 
						|
            value = value.toLowerCase(); | 
						|
 | 
						|
            return function equalsIC(elem) { | 
						|
                var attr = adapter.getAttributeValue(elem, name); | 
						|
                return attr != null && attr.toLowerCase() === value && next(elem); | 
						|
            }; | 
						|
        } | 
						|
 | 
						|
        return function equals(elem) { | 
						|
            return adapter.getAttributeValue(elem, name) === value && next(elem); | 
						|
        }; | 
						|
    }, | 
						|
    hyphen: function(next, data, options) { | 
						|
        var name = data.name; | 
						|
        var value = data.value; | 
						|
        var len = value.length; | 
						|
        var adapter = options.adapter; | 
						|
 | 
						|
        if (data.ignoreCase) { | 
						|
            value = value.toLowerCase(); | 
						|
 | 
						|
            return function hyphenIC(elem) { | 
						|
                var 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) { | 
						|
            var attr = adapter.getAttributeValue(elem, name); | 
						|
            return ( | 
						|
                attr != null && | 
						|
                attr.substr(0, len) === value && | 
						|
                (attr.length === len || attr.charAt(len) === "-") && | 
						|
                next(elem) | 
						|
            ); | 
						|
        }; | 
						|
    }, | 
						|
    element: function(next, data, options) { | 
						|
        var name = data.name; | 
						|
        var value = data.value; | 
						|
        var adapter = options.adapter; | 
						|
 | 
						|
        if (/\s/.test(value)) { | 
						|
            return falseFunc; | 
						|
        } | 
						|
 | 
						|
        value = value.replace(reChars, "\\$&"); | 
						|
 | 
						|
        var pattern = "(?:^|\\s)" + value + "(?:$|\\s)", | 
						|
            flags = data.ignoreCase ? "i" : "", | 
						|
            regex = new RegExp(pattern, flags); | 
						|
 | 
						|
        return function element(elem) { | 
						|
            var attr = adapter.getAttributeValue(elem, name); | 
						|
            return attr != null && regex.test(attr) && next(elem); | 
						|
        }; | 
						|
    }, | 
						|
    exists: function(next, data, options) { | 
						|
        var name = data.name; | 
						|
        var adapter = options.adapter; | 
						|
 | 
						|
        return function exists(elem) { | 
						|
            return adapter.hasAttrib(elem, name) && next(elem); | 
						|
        }; | 
						|
    }, | 
						|
    start: function(next, data, options) { | 
						|
        var name = data.name; | 
						|
        var value = data.value; | 
						|
        var len = value.length; | 
						|
        var adapter = options.adapter; | 
						|
 | 
						|
        if (len === 0) { | 
						|
            return falseFunc; | 
						|
        } | 
						|
 | 
						|
        if (data.ignoreCase) { | 
						|
            value = value.toLowerCase(); | 
						|
 | 
						|
            return function startIC(elem) { | 
						|
                var attr = adapter.getAttributeValue(elem, name); | 
						|
                return attr != null && attr.substr(0, len).toLowerCase() === value && next(elem); | 
						|
            }; | 
						|
        } | 
						|
 | 
						|
        return function start(elem) { | 
						|
            var attr = adapter.getAttributeValue(elem, name); | 
						|
            return attr != null && attr.substr(0, len) === value && next(elem); | 
						|
        }; | 
						|
    }, | 
						|
    end: function(next, data, options) { | 
						|
        var name = data.name; | 
						|
        var value = data.value; | 
						|
        var len = -value.length; | 
						|
        var adapter = options.adapter; | 
						|
 | 
						|
        if (len === 0) { | 
						|
            return falseFunc; | 
						|
        } | 
						|
 | 
						|
        if (data.ignoreCase) { | 
						|
            value = value.toLowerCase(); | 
						|
 | 
						|
            return function endIC(elem) { | 
						|
                var attr = adapter.getAttributeValue(elem, name); | 
						|
                return attr != null && attr.substr(len).toLowerCase() === value && next(elem); | 
						|
            }; | 
						|
        } | 
						|
 | 
						|
        return function end(elem) { | 
						|
            var attr = adapter.getAttributeValue(elem, name); | 
						|
            return attr != null && attr.substr(len) === value && next(elem); | 
						|
        }; | 
						|
    }, | 
						|
    any: function(next, data, options) { | 
						|
        var name = data.name; | 
						|
        var value = data.value; | 
						|
        var adapter = options.adapter; | 
						|
 | 
						|
        if (value === "") { | 
						|
            return falseFunc; | 
						|
        } | 
						|
 | 
						|
        if (data.ignoreCase) { | 
						|
            var regex = new RegExp(value.replace(reChars, "\\$&"), "i"); | 
						|
 | 
						|
            return function anyIC(elem) { | 
						|
                var attr = adapter.getAttributeValue(elem, name); | 
						|
                return attr != null && regex.test(attr) && next(elem); | 
						|
            }; | 
						|
        } | 
						|
 | 
						|
        return function any(elem) { | 
						|
            var attr = adapter.getAttributeValue(elem, name); | 
						|
            return attr != null && attr.indexOf(value) >= 0 && next(elem); | 
						|
        }; | 
						|
    }, | 
						|
    not: function(next, data, options) { | 
						|
        var name = data.name; | 
						|
        var value = data.value; | 
						|
        var adapter = options.adapter; | 
						|
 | 
						|
        if (value === "") { | 
						|
            return function notEmpty(elem) { | 
						|
                return !!adapter.getAttributeValue(elem, name) && next(elem); | 
						|
            }; | 
						|
        } else if (data.ignoreCase) { | 
						|
            value = value.toLowerCase(); | 
						|
 | 
						|
            return function notIC(elem) { | 
						|
                var attr = adapter.getAttributeValue(elem, name); | 
						|
                return attr != null && attr.toLowerCase() !== value && next(elem); | 
						|
            }; | 
						|
        } | 
						|
 | 
						|
        return function not(elem) { | 
						|
            return adapter.getAttributeValue(elem, name) !== value && next(elem); | 
						|
        }; | 
						|
    } | 
						|
}; | 
						|
 | 
						|
module.exports = { | 
						|
    compile: function(next, data, options) { | 
						|
        if (options && options.strict && (data.ignoreCase || data.action === "not")) { | 
						|
            throw new Error("Unsupported attribute selector"); | 
						|
        } | 
						|
        return attributeRules[data.action](next, data, options); | 
						|
    }, | 
						|
    rules: attributeRules | 
						|
};
 | 
						|
 |