Skip to content

Commit 5ac2aa8

Browse files
author
annbgn
committed
add suppport for [of S]? part in nth-child's arguments
1 parent ffb931c commit 5ac2aa8

File tree

3 files changed

+22
-5
lines changed

3 files changed

+22
-5
lines changed

cssselect/parser.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -614,12 +614,13 @@ def parse_series(tokens):
614614
Parses the arguments for :nth-child() and friends.
615615
616616
:raises: A list of tokens
617-
:returns: :``(a, b)``
617+
:returns: :``(a, b, c?)``
618618
619619
"""
620620
for token in tokens:
621621
if token.type == 'STRING':
622622
raise ValueError('String tokens not allowed in series.')
623+
623624
s = ''.join(token.value for token in tokens).strip()
624625
if s == 'odd':
625626
return 2, 1
@@ -630,7 +631,8 @@ def parse_series(tokens):
630631
if 'n' not in s:
631632
# Just b
632633
return 0, int(s)
633-
a, b = s.split('n', 1)
634+
s, *subselector = s.split("of")
635+
a, b = s.split("n", 1)
634636
if not a:
635637
a = 1
636638
elif a == '-' or a == '+':
@@ -641,7 +643,11 @@ def parse_series(tokens):
641643
b = 0
642644
else:
643645
b = int(b)
644-
return a, b
646+
if not subselector:
647+
c = 0
648+
else:
649+
c = subselector[0]
650+
return a, b, c
645651

646652

647653
#### Token objects

cssselect/xpath.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ def xpath_indirect_adjacent_combinator(self, left, right):
375375
def xpath_nth_child_function(self, xpath, function, last=False,
376376
add_name_test=True):
377377
try:
378-
a, b = parse_series(function.arguments)
378+
a, b, c = parse_series(function.arguments)
379379
except ValueError:
380380
raise ExpressionError("Invalid series: '%r'" % function.arguments)
381381

@@ -439,7 +439,9 @@ def xpath_nth_child_function(self, xpath, function, last=False,
439439
# `add_name_test` boolean is inverted and somewhat counter-intuitive:
440440
#
441441
# nth_of_type() calls nth_child(add_name_test=False)
442-
if add_name_test:
442+
if c:
443+
nodetest = self.xpath(parse(c)[0].parsed_tree).element
444+
elif add_name_test:
443445
nodetest = '*'
444446
else:
445447
nodetest = '%s' % xpath.element

tests/test_cssselect.py

+9
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,15 @@ def xpath(css):
406406
"@hreflang = 'en' or starts-with(@hreflang, 'en-'))]")
407407

408408
# --- nth-* and nth-last-* -------------------------------------
409+
assert (
410+
xpath("e:nth-child(2n+1 of S)")
411+
== "e[count(preceding-sibling::S) mod 2 = 0]"
412+
)
413+
assert (
414+
xpath("e:nth-of-type(2n+1 of S)")
415+
== "e[count(preceding-sibling::S) mod 2 = 0]"
416+
)
417+
# assert xpath('e:nth-child(2n+1 of li.important)') == "e[count(preceding-sibling::e[@class and contains(concat(' ', normalize-space(@class), ' '), ' important ')]) mod 2 = 0"
409418
assert xpath('e:nth-child(1)') == (
410419
"e[count(preceding-sibling::*) = 0]")
411420

0 commit comments

Comments
 (0)