Basic support for :nth-child()
This already includes support for formulas such as 2n, odd, even and 2n+1. Negative formulas, just "n" and others are not yet supported.
This commit is contained in:
parent
46646e2ace
commit
87f6b9c723
|
@ -259,8 +259,19 @@ rule
|
||||||
| selector
|
| selector
|
||||||
;
|
;
|
||||||
|
|
||||||
|
string
|
||||||
|
: T_STRING { s(:string, val[0]) }
|
||||||
|
;
|
||||||
|
|
||||||
|
integer
|
||||||
|
: T_INT { s(:int, val[0].to_i) }
|
||||||
|
;
|
||||||
|
|
||||||
|
# These AST nodes are _not_ the final AST nodes. Instead they are used by
|
||||||
|
# on_pseudo_class_nth_child() to determine what the final AST should be.
|
||||||
|
|
||||||
nth
|
nth
|
||||||
: T_NTH { s(:nth) }
|
: T_NTH { s(:nth, s(:int, 1)) }
|
||||||
| T_MINUS T_NTH { s(:nth) }
|
| T_MINUS T_NTH { s(:nth) }
|
||||||
| integer T_NTH { s(:nth, val[0]) }
|
| integer T_NTH { s(:nth, val[0]) }
|
||||||
| integer T_NTH integer { s(:nth, val[0], val[2]) }
|
| integer T_NTH integer { s(:nth, val[0], val[2]) }
|
||||||
|
@ -273,14 +284,6 @@ rule
|
||||||
even
|
even
|
||||||
: T_EVEN { s(:nth, s(:int, 2)) }
|
: T_EVEN { s(:nth, s(:int, 2)) }
|
||||||
;
|
;
|
||||||
|
|
||||||
string
|
|
||||||
: T_STRING { s(:string, val[0]) }
|
|
||||||
;
|
|
||||||
|
|
||||||
integer
|
|
||||||
: T_INT { s(:int, val[0].to_i) }
|
|
||||||
;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---- inner
|
---- inner
|
||||||
|
@ -347,4 +350,45 @@ end
|
||||||
def on_pseudo_class_root
|
def on_pseudo_class_root
|
||||||
return s(:call, 'not', s(:axis, 'parent', s(:test, nil, '*')))
|
return s(:call, 'not', s(:axis, 'parent', s(:test, nil, '*')))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Generates the AST for the `nth-child` pseudo class.
|
||||||
|
#
|
||||||
|
# @param [AST::Node] arg
|
||||||
|
# @return [AST::Node]
|
||||||
|
#
|
||||||
|
def on_pseudo_class_nth_child(arg)
|
||||||
|
if arg.type == :int
|
||||||
|
node = s(
|
||||||
|
:eq,
|
||||||
|
s(
|
||||||
|
:call,
|
||||||
|
'count',
|
||||||
|
s(:axis, 'preceding-sibling', s(:test, nil, '*'))
|
||||||
|
),
|
||||||
|
s(:int, arg.children[0] - 1)
|
||||||
|
)
|
||||||
|
else
|
||||||
|
step, offset = *arg
|
||||||
|
|
||||||
|
before_count = s(
|
||||||
|
:add,
|
||||||
|
s(:call, 'count', s(:axis, 'preceding-sibling', s(:test, nil, '*'))),
|
||||||
|
s(:int, 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
if offset
|
||||||
|
node = s(
|
||||||
|
:and,
|
||||||
|
s(:gte, before_count, offset),
|
||||||
|
s(:eq, s(:mod, s(:sub, before_count, offset), s(:int, 2)), s(:int, 0))
|
||||||
|
)
|
||||||
|
else
|
||||||
|
node = s(:mod, before_count, step)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return node
|
||||||
|
end
|
||||||
|
|
||||||
# vim: set ft=racc:
|
# vim: set ft=racc:
|
||||||
|
|
|
@ -15,38 +15,33 @@ describe Oga::CSS::Parser do
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the x:nth-child(1) pseudo class' do
|
example 'parse the x:nth-child(1) pseudo class' do
|
||||||
parse_css('x:nth-child(1)').should == s(
|
parse_css('x:nth-child(1)').should == parse_xpath(
|
||||||
:pseudo,
|
'descendant-or-self::x[count(preceding-sibling::*) = 0]'
|
||||||
s(:test, nil, 'x'),
|
|
||||||
'nth-child',
|
|
||||||
s(:int, 1)
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the :nth-child(1) pseudo class' do
|
example 'parse the :nth-child(1) pseudo class' do
|
||||||
parse_css(':nth-child(1)').should == s(
|
parse_css(':nth-child(1)').should == parse_xpath(
|
||||||
:pseudo,
|
'descendant-or-self::*[count(preceding-sibling::*) = 0]'
|
||||||
nil,
|
|
||||||
'nth-child',
|
|
||||||
s(:int, 1)
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the x:nth-child(odd) pseudo class' do
|
example 'parse the :nth-child(2) pseudo class' do
|
||||||
parse_css('x:nth-child(odd)').should == s(
|
parse_css(':nth-child(2)').should == parse_xpath(
|
||||||
:pseudo,
|
'descendant-or-self::*[count(preceding-sibling::*) = 1]'
|
||||||
s(:test, nil, 'x'),
|
|
||||||
'nth-child',
|
|
||||||
s(:odd)
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the x:nth-child(even) pseudo class' do
|
example 'parse the x:nth-child(even) pseudo class' do
|
||||||
parse_css('x:nth-child(even)').should == s(
|
parse_css('x:nth-child(even)').should == parse_xpath(
|
||||||
:pseudo,
|
'descendant-or-self::x[(count(preceding-sibling::*) + 1) mod 2]'
|
||||||
s(:test, nil, 'x'),
|
)
|
||||||
'nth-child',
|
end
|
||||||
s(:even)
|
|
||||||
|
example 'parse the x:nth-child(odd) pseudo class' do
|
||||||
|
parse_css('x:nth-child(odd)').should == parse_xpath(
|
||||||
|
'descendant-or-self::x[(count(preceding-sibling::*) + 1) >= 1 ' \
|
||||||
|
'and (((count(preceding-sibling::*) + 1) - 1) mod 2) = 0]'
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue