diff --git a/lib/nokogiri/css/xpath_visitor.rb b/lib/nokogiri/css/xpath_visitor.rb index ba63f3c4122..6d8ab67ce69 100644 --- a/lib/nokogiri/css/xpath_visitor.rb +++ b/lib/nokogiri/css/xpath_visitor.rb @@ -302,7 +302,7 @@ def nth(node, options = {}) end def read_a_and_positive_b(values) - op = values[2] + op = values[2].strip if op == "+" a = values[0].to_i b = values[3].to_i diff --git a/test/css/test_css_integration.rb b/test/css/test_css_integration.rb index 9a0b47ce599..3d0e488f56e 100644 --- a/test/css/test_css_integration.rb +++ b/test/css/test_css_integration.rb @@ -194,6 +194,7 @@ def assert_result_rows(intarray, result, word = "row") assert_result_rows([5], subject.search("table//tr:nth-child(5)")) assert_result_rows([1, 3], subject.search("div/h1.c:nth-child(2)"), "header") assert_result_rows([3, 4], subject.search("div/i.b:nth-child(2n+1)"), "italic") + assert_result_rows([3, 4], subject.search("div/i.b:nth-child(2n + 1)"), "italic") end it "selects first_of_type" do diff --git a/test/css/test_tokenizer.rb b/test/css/test_tokenizer.rb index 878b708f4b1..5df220aba4c 100644 --- a/test/css/test_tokenizer.rb +++ b/test/css/test_tokenizer.rb @@ -226,6 +226,21 @@ def test_scan_nth @scanner, ) + @scanner.scan("x:nth-child(5n + 3)") + assert_tokens( + [ + [:IDENT, "x"], + [":", ":"], + [:FUNCTION, "nth-child("], + [:NUMBER, "5"], + [:IDENT, "n"], + [:PLUS, " + "], + [:NUMBER, "3"], + [:RPAREN, ")"], + ], + @scanner, + ) + @scanner.scan("x:nth-child(-1n+3)") assert_tokens( [ diff --git a/test/css/test_xpath_visitor.rb b/test/css/test_xpath_visitor.rb index 4dbd2ff3219..5a5be68e13e 100644 --- a/test/css/test_xpath_visitor.rb +++ b/test/css/test_xpath_visitor.rb @@ -289,10 +289,12 @@ def assert_xpath(expecteds, asts) it ":nth(an+b)" do assert_xpath("//a[(position() mod 2)=0]", parser.parse("a:nth-of-type(2n)")) assert_xpath("//a[(position()>=1) and (((position()-1) mod 2)=0)]", parser.parse("a:nth-of-type(2n+1)")) + assert_xpath("//a[(position()>=1) and (((position()-1) mod 2)=0)]", parser.parse("a:nth-of-type(2n + 1)")) assert_xpath("//a[(position() mod 2)=0]", parser.parse("a:nth-of-type(even)")) assert_xpath("//a[(position()>=1) and (((position()-1) mod 2)=0)]", parser.parse("a:nth-of-type(odd)")) assert_xpath("//a[(position()>=3) and (((position()-3) mod 4)=0)]", parser.parse("a:nth-of-type(4n+3)")) assert_xpath("//a[position()<=3]", parser.parse("a:nth-of-type(-1n+3)")) + assert_xpath("//a[position()<=3]", parser.parse("a:nth-of-type(-1n + 3)")) assert_xpath("//a[position()<=3]", parser.parse("a:nth-of-type(-n+3)")) assert_xpath("//a[position()>=3]", parser.parse("a:nth-of-type(1n+3)")) assert_xpath("//a[position()>=3]", parser.parse("a:nth-of-type(n+3)"))