Parsing support for :nth-last-child.

This commit is contained in:
Yorick Peterse 2014-11-01 20:58:28 +01:00
parent 64f9c570fa
commit 9cce93fc4a
2 changed files with 118 additions and 17 deletions

View File

@ -379,26 +379,32 @@ end
# @return [AST::Node]
#
def on_pseudo_class_nth_child(arg)
# literal 2, 4, etc
return generate_nth_child('preceding-sibling', arg)
end
##
# Generates the AST for the `nth-last-child` pseudo class.
#
# @param [AST::Node] arg
# @return [AST::Node]
#
def on_pseudo_class_nth_last_child(arg)
return generate_nth_child('following-sibling', arg)
end
##
# @param [String] count_axis
# @param [AST::Node] arg
# @return [AST::Node]
#
def generate_nth_child(count_axis, arg)
count_call = s(:call, 'count', s(:axis, count_axis, s(:test, nil, '*')))
# literal 2, 4, etc
if arg.type == :int
node = s(
:eq,
s(
:call,
'count',
s(:axis, 'preceding-sibling', s(:test, nil, '*'))
),
s(:int, arg.children[0] - 1)
)
node = s(:eq, count_call, s(:int, arg.children[0] - 1))
else
step, offset = *arg
count_call = s(
:call,
'count',
s(:axis, 'preceding-sibling', s(:test, nil, '*'))
)
before_count = s(:add, count_call, s(:int, 1))
if step and step.children[0] >= 0

View File

@ -0,0 +1,95 @@
require 'spec_helper'
describe Oga::CSS::Parser do
context ':nth-last-child pseudo class' do
example 'parse the x:nth-last-child(1) pseudo class' do
parse_css('x:nth-last-child(1)').should == parse_xpath(
'descendant-or-self::x[count(following-sibling::*) = 0]'
)
end
example 'parse the :nth-last-child(1) pseudo class' do
parse_css(':nth-last-child(1)').should == parse_xpath(
'descendant-or-self::*[count(following-sibling::*) = 0]'
)
end
example 'parse the :nth-last-child(2) pseudo class' do
parse_css(':nth-last-child(2)').should == parse_xpath(
'descendant-or-self::*[count(following-sibling::*) = 1]'
)
end
example 'parse the x:nth-last-child(even) pseudo class' do
parse_css('x:nth-last-child(even)').should == parse_xpath(
'descendant-or-self::x[((count(following-sibling::*) + 1) mod 2) = 0]'
)
end
example 'parse the x:nth-last-child(odd) pseudo class' do
parse_css('x:nth-last-child(odd)').should == parse_xpath(
'descendant-or-self::x[(count(following-sibling::*) + 1) >= 1 ' \
'and (((count(following-sibling::*) + 1) - 1) mod 2) = 0]'
)
end
example 'parse the x:nth-last-child(n) pseudo class' do
parse_css('x:nth-last-child(n)').should == parse_xpath(
'descendant-or-self::x[((count(following-sibling::*) + 1) mod 1) = 0]'
)
end
example 'parse the x:nth-last-child(-n) pseudo class' do
parse_css('x:nth-last-child(-n)').should == parse_xpath(
'descendant-or-self::x[((count(following-sibling::*) + 1) mod 1) = 0]'
)
end
example 'parse the x:nth-last-child(-n+6) pseudo class' do
parse_css('x:nth-last-child(-n+6)').should == parse_xpath(
'descendant-or-self::x[((count(following-sibling::*) + 1) <= 6) ' \
'and (((count(following-sibling::*) + 1) - 6) mod 1) = 0]'
)
end
example 'parse the x:nth-last-child(-n-6) pseudo class' do
parse_css('x:nth-last-child(-n-6)').should == parse_xpath(
'descendant-or-self::x[count(following-sibling::*) = -1]'
)
end
example 'parse the x:nth-last-child(2n) pseudo class' do
parse_css('x:nth-last-child(2n)').should == parse_css(
'x:nth-last-child(even)'
)
end
example 'parse the x:nth-last-child(2n+1) pseudo class' do
parse_css('x:nth-last-child(2n+1)').should == parse_xpath(
'descendant-or-self::x[(count(following-sibling::*) + 1) >= 1 ' \
'and (((count(following-sibling::*) + 1) - 1) mod 2) = 0]'
)
end
example 'parse the x:nth-last-child(2n-6) pseudo class' do
parse_css('x:nth-last-child(2n-6)').should == parse_xpath(
'descendant-or-self::x[(count(following-sibling::*) + 1) >= 2 ' \
'and (((count(following-sibling::*) + 1) - 2) mod 2) = 0]'
)
end
example 'parse the x:nth-last-child(-2n-6) pseudo class' do
parse_css('x:nth-last-child(-2n-6)').should == parse_xpath(
'descendant-or-self::x[((count(following-sibling::*) + 1) <= -2) ' \
'and (((count(following-sibling::*) + 1) - -2) mod 2) = 0]'
)
end
example 'parse the x:nth-last-child(-2n+6) pseudo class' do
parse_css('x:nth-last-child(-2n+6)').should == parse_xpath(
'descendant-or-self::x[((count(following-sibling::*) + 1) <= 6) ' \
'and (((count(following-sibling::*) + 1) - 6) mod 2) = 0]'
)
end
end
end