Parsing support for nth-child(n+X)

This commit is contained in:
Yorick Peterse 2014-11-02 19:29:09 +01:00
parent 8d8d74ec41
commit 0faceffacb
2 changed files with 40 additions and 20 deletions

View File

@ -274,11 +274,14 @@ rule
# n # n
: T_NTH { s(:nth, s(:int, 1)) } : T_NTH { s(:nth, s(:int, 1)) }
# n+2
| T_NTH integer { s(:nth, s(:int, 1), val[1]) }
# -n # -n
| T_MINUS T_NTH { s(:nth, s(:int, 1)) } | T_MINUS T_NTH { s(:nth, s(:int, 1)) }
# -n+2, -n-2 # -n+2, -n-2
| T_MINUS T_NTH integer { s(:nth, nil, val[2]) } | T_MINUS T_NTH integer { s(:nth, s(:int, -1), val[2]) }
# 2n # 2n
| integer T_NTH { s(:nth, val[0]) } | integer T_NTH { s(:nth, val[0]) }
@ -406,27 +409,11 @@ end
else else
step, offset = *arg step, offset = *arg
before_count = s(:add, count_call, s(:int, 1)) before_count = s(:add, count_call, s(:int, 1))
compare = step_comparison(step)
if step and step.children[0] >= 0
compare = :gte
else
compare = :lte
end
# 2n+2, 2n-4, etc # 2n+2, 2n-4, etc
if offset if offset
# -2n mod_val = step_modulo_value(step)
if step and non_positive_number?(step)
mod_val = s(:int, -step.children[0])
# 2n
elsif step
mod_val = step
else
mod_val = s(:int, 1)
end
node = s( node = s(
:and, :and,
s(compare, before_count, offset), s(compare, before_count, offset),
@ -460,4 +447,30 @@ end
return node.children[0] <= 0 return node.children[0] <= 0
end end
##
# @param [AST::Node] node
# @return [Symbol]
#
def step_comparison(node)
return node.children[0] >= 0 ? :gte : :lte
end
##
# @param [AST::Node] node
# @return [AST::Node]
#
def step_modulo_value(step)
# -2n
if step and non_positive_number?(step)
mod_val = s(:int, -step.children[0])
# 2n
elsif step
mod_val = step
else
mod_val = s(:int, 1)
end
end
# vim: set ft=racc: # vim: set ft=racc:

View File

@ -52,6 +52,13 @@ describe Oga::CSS::Parser do
) )
end end
example 'parse the x:nth-child(n+5) pseudo class' do
parse_css('x:nth-child(n+5)').should == parse_xpath(
'descendant-or-self::x[(count(preceding-sibling::*) + 1) >= 5 ' \
'and (((count(preceding-sibling::*) + 1) - 5) mod 1) = 0]'
)
end
example 'parse the x:nth-child(2n) pseudo class' do example 'parse the x:nth-child(2n) pseudo class' do
parse_css('x:nth-child(2n)').should == parse_css('x:nth-child(even)') parse_css('x:nth-child(2n)').should == parse_css('x:nth-child(even)')
end end