Skip to content

Commit

Permalink
supporting :has() selectors. closes #172
Browse files Browse the repository at this point in the history
  • Loading branch information
tenderlove committed Nov 30, 2009
1 parent c0fbd68 commit af2856a
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* XML::NodeSet#reverse added
* Added fragment support to Node#add_child, Node#add_next_sibling,
Node#add_previous_sibling, and Node#replace.
* Ths CSS selector engine now supports :has()

* Bugfixes

Expand Down
5 changes: 4 additions & 1 deletion lib/nokogiri/css/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class Nokogiri::CSS::GeneratedParser

token FUNCTION INCLUDES DASHMATCH LBRACE HASH PLUS GREATER S STRING IDENT
token COMMA NUMBER PREFIXMATCH SUFFIXMATCH SUBSTRINGMATCH TILDE NOT_EQUAL
token SLASH DOUBLESLASH NOT EQUAL RPAREN LSQUARE RSQUARE
token SLASH DOUBLESLASH NOT EQUAL RPAREN LSQUARE RSQUARE HAS

rule
selector
Expand Down Expand Up @@ -112,6 +112,9 @@ rule
| NOT expr RPAREN {
result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
}
| HAS selector RPAREN {
result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
}
;
expr
: NUMBER COMMA expr { result = [val.first, val.last] }
Expand Down
3 changes: 2 additions & 1 deletion lib/nokogiri/css/tokenizer.rex
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ rule
# [:state] pattern [actions]
{ident}\(\s* { [:FUNCTION, text] }
\has\({w} { [:HAS, text] }
{ident}\({w} { [:FUNCTION, text] }
{ident} { [:IDENT, text] }
\#{name} { [:HASH, text] }
{w}~={w} { [:INCLUDES, text] }
Expand Down
2 changes: 2 additions & 0 deletions lib/nokogiri/css/xpath_visitor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ def visit_function node
"last() = 1"
when /^comment\(/
"comment()"
when /^has\(/
node.value[1].accept(self)
else
args = ['.'] + node.value[1..-1]
"#{node.value.first}#{args.join(', ')})"
Expand Down
5 changes: 5 additions & 0 deletions test/css/test_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ def test_to_a
)
end

def test_has
assert_xpath "//a[b]", @parser.parse("a:has(b)")
assert_xpath "//a[b/c]", @parser.parse("a:has(b > c)")
end

def test_dashmatch
assert_xpath "//a[@class = 'bar' or starts-with(@class, concat('bar', '-'))]",
@parser.parse("a[@class|='bar']")
Expand Down
7 changes: 7 additions & 0 deletions test/css/test_tokenizer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ def setup
@scanner = Nokogiri::CSS::Tokenizer.new
end

def test_has
@scanner.scan("a:has(b)")
assert_tokens(
[[:IDENT, "a"], [":", ":"], [:HAS, "has("], [:IDENT, "b"], [:RPAREN, ")"]],
@scanner)
end

def test_unicode
@scanner.scan("a日本語")
assert_tokens([[:IDENT, 'a日本語']], @scanner)
Expand Down

0 comments on commit af2856a

Please sign in to comment.