diff --git a/lib/tools/selector.dart b/lib/tools/selector.dart index c3ad253a6..1db5a5bab 100644 --- a/lib/tools/selector.dart +++ b/lib/tools/selector.dart @@ -11,7 +11,7 @@ class ContainsSelector { } } -RegExp _SELECTOR_REGEXP = new RegExp(r'^(?:([\w\-]+)|(?:\.([\w\-]+))|(?:\[([\w\-]+)(?:=([^\]]*))?\]))'); +RegExp _SELECTOR_REGEXP = new RegExp(r'^(?:([\w\-]+)|(?:\.([\w\-]+))|(?:\[([\w\-\*]+)(?:=([^\]]*))?\]))'); RegExp _COMMENT_COMPONENT_REGEXP = new RegExp(r'^\[([\w\-]+)(?:\=(.*))?\]$'); RegExp _CONTAINS_REGEXP = new RegExp(r'^:contains\(\/(.+)\/\)$'); // RegExp _ATTR_CONTAINS_REGEXP = new RegExp(r'^\[\*=\/(.+)\/\]$'); // @@ -101,9 +101,10 @@ bool matchesNode(Node node, String selector) { stillGood = false; } } else if (part.attrName != null) { - if (part.attrValue == '' ? - node.attributes[part.attrName] == null : - node.attributes[part.attrName] != part.attrValue) { + String matchingKey = _matchingKey(node.attributes.keys, part.attrName); + if (matchingKey == null || part.attrValue == '' ? + node.attributes[matchingKey] == null : + node.attributes[matchingKey] != part.attrValue) { stillGood = false; } } @@ -122,3 +123,8 @@ bool matchesNode(Node node, String selector) { } return false; } + +String _matchingKey(Iterable keys, String attrName) => + keys.firstWhere( + (key) => new RegExp('^${attrName.replaceAll('*', r'[\w\-]+')}\$').hasMatch(key.toString()), + orElse: () => null); diff --git a/test/tools/selector_spec.dart b/test/tools/selector_spec.dart index 9e6b40b88..3c9a13938 100644 --- a/test/tools/selector_spec.dart +++ b/test/tools/selector_spec.dart @@ -57,6 +57,16 @@ main() => describe('selector', () { expect(matchesNode(node, '[*=/xyzz/]'), isFalse); }); + it('should match whildcard attributes', () { + var node = new Element.html('
'); + expect(matchesNode(node, '[attr-*]'), isTrue); + expect(matchesNode(node, '[attr-*=blah]'), isTrue); + expect(matchesNode(node, '[attr-*=halb]'), isFalse); + expect(matchesNode(node, '[foo-*]'), isFalse); + expect(matchesNode(node, '[foo-*=blah]'), isFalse); + expect(matchesNode(node, '[foo-*=halb]'), isFalse); + }); + it('should match text', () { var node = new Text('before-abc-after'); expect(matchesNode(node, ':contains(/abc/)'), isTrue);