From ffe650fbf70014cd8c59b5792d6181ca6d550564 Mon Sep 17 00:00:00 2001 From: Mark Oleson Date: Fri, 10 Nov 2023 11:07:25 -0500 Subject: [PATCH 1/2] fix: strip spaces from the operator when translating nth css to xpath --- lib/nokogiri/css/xpath_visitor.rb | 2 +- test/css/test_css_integration.rb | 1 + test/css/test_tokenizer.rb | 15 +++++++++++++++ test/css/test_xpath_visitor.rb | 2 ++ 4 files changed, 19 insertions(+), 1 deletion(-) 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)")) From 650ee8156fd613a4d12ce3e56518ebc0f4f78f3b Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Mon, 13 Nov 2023 14:35:14 -0500 Subject: [PATCH 2/2] update CHANGELOG --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9ac8629bd8..59eef29adb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,10 @@ Documentation on what can be matched: * [`XML::NodeSet#deconstruct`](https://nokogiri.org/rdoc/Nokogiri/XML/NodeSet.html?h=deconstruct#method-i-deconstruct) +### Fixed + +* CSS `nth` pseudo-classes now handle spaces, e.g. `"2n + 1"`. [#3018] @fusion2004 + ## 1.15.4 / 2023-08-11