Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
unescape css identifiers to allow use in css queries
Browse files Browse the repository at this point in the history
twalpole committed Jun 17, 2015

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 1be8831 commit 82a63c8
Showing 3 changed files with 22 additions and 5 deletions.
10 changes: 8 additions & 2 deletions lib/nokogiri/css/parser.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions lib/nokogiri/css/parser.y
Original file line number Diff line number Diff line change
@@ -55,7 +55,7 @@ rule
| simple_selector
;
class
: '.' IDENT { result = Node.new(:CLASS_CONDITION, [val[1]]) }
: '.' IDENT { result = Node.new(:CLASS_CONDITION, [unescape_css_identifier(val[1])]) }
;
element_name
: namespaced_ident
@@ -218,7 +218,7 @@ rule
| negation
;
attribute_id
: HASH { result = Node.new(:ID, val) }
: HASH { result = Node.new(:ID, [unescape_css_identifier(val.first)]) }
;
attrib_val_0or1
: eql_incl_dash IDENT { result = [val.first, val[1]] }
@@ -254,3 +254,8 @@ end

require 'nokogiri/css/parser_extras'

---- inner

def unescape_css_identifier(identifier)
identifier.gsub(/\\(?:([^0-9a-fA-F])|([0-9a-fA-F]{1,6})\s?)/){ |m| $1 || [$2.hex].pack('U') }
end
8 changes: 7 additions & 1 deletion test/css/test_parser.rb
Original file line number Diff line number Diff line change
@@ -160,7 +160,7 @@ def test_standard_nth_selectors
assert_xpath '//a[position() = 1]', @parser.parse('a:first-of-type') # no parens
assert_xpath "//a[contains(concat(' ', normalize-space(@class), ' '), ' b ')][position() = 1]",
@parser.parse('a.b:first-of-type') # no parens
assert_xpath '//a[position() = 99]', @parser.parse('a:nth-of-type(99)')
assert_xpath '//a[position() = 99]', @parser.parse('a:nth-of-type(99)')
assert_xpath "//a[contains(concat(' ', normalize-space(@class), ' '), ' b ')][position() = 99]",
@parser.parse('a.b:nth-of-type(99)')
assert_xpath '//a[position() = last()]', @parser.parse('a:last-of-type()')
@@ -259,6 +259,10 @@ def test_attribute

def test_id
assert_xpath "//*[@id = 'foo']", @parser.parse('#foo')
assert_xpath "//*[@id = 'escape:needed,']", @parser.parse('#escape\:needed\,')
assert_xpath "//*[@id = 'escape:needed,']", @parser.parse('#escape\3Aneeded\,')
assert_xpath "//*[@id = 'escape:needed,']", @parser.parse('#escape\3A needed\2C')
assert_xpath "//*[@id = 'escape:needed']", @parser.parse('#escape\00003Aneeded')
end

def test_pseudo_class_no_ident
@@ -294,6 +298,8 @@ def test_class
@parser.parse('foo.awesome')
assert_xpath "//foo//*[contains(concat(' ', normalize-space(@class), ' '), ' awesome ')]",
@parser.parse('foo .awesome')
assert_xpath "//foo//*[contains(concat(' ', normalize-space(@class), ' '), ' awe.some ')]",
@parser.parse('foo .awe\.some')
end

def test_bare_not

0 comments on commit 82a63c8

Please sign in to comment.