in lib/src/query_selector.dart [134:181]
bool visitPseudoClassSelector(PseudoClassSelector node) {
switch (node.name) {
// http://dev.w3.org/csswg/selectors-4/#structural-pseudos
// http://dev.w3.org/csswg/selectors-4/#the-root-pseudo
case 'root':
// TODO(jmesserly): fix when we have a .ownerDocument pointer
// return _element == _element.ownerDocument.rootElement;
return _element!.localName == 'html' && _element!.parentNode == null;
// http://dev.w3.org/csswg/selectors-4/#the-empty-pseudo
case 'empty':
return _element!.nodes
.any((n) => !(n is Element || n is Text && n.text.isNotEmpty));
// http://dev.w3.org/csswg/selectors-4/#the-blank-pseudo
case 'blank':
return _element!.nodes.any((n) => !(n is Element ||
n is Text && n.text.runes.any((r) => !isWhitespaceCC(r))));
// http://dev.w3.org/csswg/selectors-4/#the-first-child-pseudo
case 'first-child':
return _element!.previousElementSibling == null;
// http://dev.w3.org/csswg/selectors-4/#the-last-child-pseudo
case 'last-child':
return _element!.nextElementSibling == null;
// http://dev.w3.org/csswg/selectors-4/#the-only-child-pseudo
case 'only-child':
return _element!.previousElementSibling == null &&
_element!.nextElementSibling == null;
// http://dev.w3.org/csswg/selectors-4/#link
case 'link':
return _element!.attributes['href'] != null;
case 'visited':
// Always return false since we aren't a browser. This is allowed per:
// http://dev.w3.org/csswg/selectors-4/#visited-pseudo
return false;
}
// :before, :after, :first-letter/line can't match DOM elements.
if (_isLegacyPsuedoClass(node.name)) return false;
throw _unimplemented(node);
}