Use the descendant axis for CSS selectors.
Instead of using "descendant-or-self" Oga will use "descendant". This ensures that expressions such as "foo *" don't return a set also including the "foo" element. Nokogiri solves this problem in a somewhat different way by using //foo//* for the CSS expression "foo *". While this works in Nokogiri the expression "descendant-or-self::node()" is slow as a snail in Oga (due to its nature of retrieving _all_ nodes first). By using "descendant" we can work around this problem.
This commit is contained in:
parent
602f2fe8bb
commit
eb3a3e7630
|
@ -45,7 +45,7 @@ rule
|
|||
;
|
||||
|
||||
descendant_or_self
|
||||
: node_test { s(:axis, 'descendant-or-self', val[0]) }
|
||||
: node_test { s(:axis, 'descendant', val[0]) }
|
||||
;
|
||||
|
||||
axis
|
||||
|
|
|
@ -3,53 +3,53 @@ require 'spec_helper'
|
|||
describe Oga::CSS::Parser do
|
||||
context 'axes' do
|
||||
example 'parse the > axis' do
|
||||
parse_css('x > y').should == parse_xpath('descendant-or-self::x/y')
|
||||
parse_css('x > y').should == parse_xpath('descendant::x/y')
|
||||
end
|
||||
|
||||
example 'parse the > axis called on another > axis' do
|
||||
parse_css('a > b > c').should == parse_xpath('descendant-or-self::a/b/c')
|
||||
parse_css('a > b > c').should == parse_xpath('descendant::a/b/c')
|
||||
end
|
||||
|
||||
example 'parse an > axis followed by an element with an ID' do
|
||||
parse_css('x > foo#bar').should == parse_xpath(
|
||||
'descendant-or-self::x/foo[@id="bar"]'
|
||||
'descendant::x/foo[@id="bar"]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse an > axis followed by an element with a class' do
|
||||
parse_css('x > foo.bar').should == parse_xpath(
|
||||
'descendant-or-self::x/foo[contains(concat(" ", @class, " "), " bar ")]'
|
||||
'descendant::x/foo[contains(concat(" ", @class, " "), " bar ")]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the + axis' do
|
||||
parse_css('x + y').should == parse_xpath(
|
||||
'descendant-or-self::x/following-sibling::*[1]/self::y'
|
||||
'descendant::x/following-sibling::*[1]/self::y'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the + axis called on another + axis' do
|
||||
parse_css('a + b + c').should == parse_xpath(
|
||||
'descendant-or-self::a/following-sibling::*[1]/self::b/' \
|
||||
'descendant::a/following-sibling::*[1]/self::b/' \
|
||||
'following-sibling::*[1]/self::c'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the ~ axis' do
|
||||
parse_css('x ~ y').should == parse_xpath(
|
||||
'descendant-or-self::x/following-sibling::y'
|
||||
'descendant::x/following-sibling::y'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the ~ axis followed by another node test' do
|
||||
parse_css('x ~ y z').should == parse_xpath(
|
||||
'descendant-or-self::x/following-sibling::y/descendant-or-self::z'
|
||||
'descendant::x/following-sibling::y/descendant::z'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the ~ axis called on another ~ axis' do
|
||||
parse_css('a ~ b ~ c').should == parse_xpath(
|
||||
'descendant-or-self::a/following-sibling::b/following-sibling::c'
|
||||
'descendant::a/following-sibling::b/following-sibling::c'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,26 +4,26 @@ describe Oga::CSS::Parser do
|
|||
context 'classes' do
|
||||
example 'parse a class selector' do
|
||||
parse_css('.foo').should == parse_xpath(
|
||||
'descendant-or-self::*[contains(concat(" ", @class, " "), " foo ")]'
|
||||
'descendant::*[contains(concat(" ", @class, " "), " foo ")]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse a selector for an element with a class' do
|
||||
parse_css('foo.bar').should == parse_xpath(
|
||||
'descendant-or-self::foo[contains(concat(" ", @class, " "), " bar ")]'
|
||||
'descendant::foo[contains(concat(" ", @class, " "), " bar ")]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse a selector using multiple classes' do
|
||||
parse_css('.foo.bar').should == parse_xpath(
|
||||
'descendant-or-self::*[contains(concat(" ", @class, " "), " foo ") ' \
|
||||
'descendant::*[contains(concat(" ", @class, " "), " foo ") ' \
|
||||
'and contains(concat(" ", @class, " "), " bar ")]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse a selector using a class and an ID' do
|
||||
parse_css('#foo.bar').should == parse_xpath(
|
||||
'descendant-or-self::*[@id="foo" and ' \
|
||||
'descendant::*[@id="foo" and ' \
|
||||
'contains(concat(" ", @class, " "), " bar ")]'
|
||||
)
|
||||
end
|
||||
|
|
|
@ -3,26 +3,22 @@ require 'spec_helper'
|
|||
describe Oga::CSS::Parser do
|
||||
context 'IDs' do
|
||||
example 'parse an ID selector' do
|
||||
parse_css('#foo').should == parse_xpath(
|
||||
'descendant-or-self::*[@id="foo"]'
|
||||
)
|
||||
parse_css('#foo').should == parse_xpath('descendant::*[@id="foo"]')
|
||||
end
|
||||
|
||||
example 'parse a selector for an element with an ID' do
|
||||
parse_css('foo#bar').should == parse_xpath(
|
||||
'descendant-or-self::foo[@id="bar"]'
|
||||
)
|
||||
parse_css('foo#bar').should == parse_xpath('descendant::foo[@id="bar"]')
|
||||
end
|
||||
|
||||
example 'parse a selector using multiple IDs' do
|
||||
parse_css('#foo#bar').should == parse_xpath(
|
||||
'descendant-or-self::*[@id="foo" and @id="bar"]'
|
||||
'descendant::*[@id="foo" and @id="bar"]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse a selector using an ID and a class' do
|
||||
parse_css('.foo#bar').should == parse_xpath(
|
||||
'descendant-or-self::*[contains(concat(" ", @class, " "), " foo ") ' \
|
||||
'descendant::*[contains(concat(" ", @class, " "), " foo ") ' \
|
||||
'and @id="bar"]'
|
||||
)
|
||||
end
|
||||
|
|
|
@ -3,40 +3,38 @@ require 'spec_helper'
|
|||
describe Oga::CSS::Parser do
|
||||
context 'operators' do
|
||||
example 'parse the = operator' do
|
||||
parse_css('x[a="b"]').should == parse_xpath(
|
||||
'descendant-or-self::x[@a="b"]'
|
||||
)
|
||||
parse_css('x[a="b"]').should == parse_xpath('descendant::x[@a="b"]')
|
||||
end
|
||||
|
||||
example 'parse the ~= operator' do
|
||||
parse_css('x[a~="b"]').should == parse_xpath(
|
||||
'descendant-or-self::x[contains(concat(" ", @a, " "), ' \
|
||||
'descendant::x[contains(concat(" ", @a, " "), ' \
|
||||
'concat(" ", "b", " "))]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the ^= operator' do
|
||||
parse_css('x[a^="b"]').should == parse_xpath(
|
||||
'descendant-or-self::x[starts-with(@a, "b")]'
|
||||
'descendant::x[starts-with(@a, "b")]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the $= operator' do
|
||||
parse_css('x[a$="b"]').should == parse_xpath(
|
||||
'descendant-or-self::x[substring(@a, string-length(@a) - ' \
|
||||
'descendant::x[substring(@a, string-length(@a) - ' \
|
||||
'string-length("b") + 1, string-length("b")) = "b"]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the *= operator' do
|
||||
parse_css('x[a*="b"]').should == parse_xpath(
|
||||
'descendant-or-self::x[contains(@a, "b")]'
|
||||
'descendant::x[contains(@a, "b")]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the |= operator' do
|
||||
parse_css('x[a|="b"]').should == parse_xpath(
|
||||
'descendant-or-self::x[@a = "b" or starts-with(@a, concat("b", "-"))]'
|
||||
'descendant::x[@a = "b" or starts-with(@a, concat("b", "-"))]'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,12 +3,12 @@ require 'spec_helper'
|
|||
describe Oga::CSS::Parser do
|
||||
context 'paths' do
|
||||
example 'parse a single path' do
|
||||
parse_css('foo').should == parse_xpath('descendant-or-self::foo')
|
||||
parse_css('foo').should == parse_xpath('descendant::foo')
|
||||
end
|
||||
|
||||
example 'parse a path using two selectors' do
|
||||
parse_css('foo bar').should == parse_xpath(
|
||||
'descendant-or-self::foo/descendant-or-self::bar'
|
||||
'descendant::foo/descendant::bar'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,20 +3,18 @@ require 'spec_helper'
|
|||
describe Oga::CSS::Parser do
|
||||
context 'predicates' do
|
||||
example 'parse a predicate' do
|
||||
parse_css('foo[bar]').should == parse_xpath(
|
||||
'descendant-or-self::foo[@bar]'
|
||||
)
|
||||
parse_css('foo[bar]').should == parse_xpath('descendant::foo[@bar]')
|
||||
end
|
||||
|
||||
example 'parse a node test followed by a node test with a predicate' do
|
||||
parse_css('foo bar[baz]').should == parse_xpath(
|
||||
'descendant-or-self::foo/descendant-or-self::bar[@baz]'
|
||||
'descendant::foo/descendant::bar[@baz]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse a predicate testing an attribute value' do
|
||||
parse_css('foo[bar="baz"]').should == parse_xpath(
|
||||
'descendant-or-self::foo[@bar="baz"]'
|
||||
'descendant::foo[@bar="baz"]'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,9 +3,7 @@ require 'spec_helper'
|
|||
describe Oga::CSS::Parser do
|
||||
context ':empty pseudo class' do
|
||||
example 'parse the :empty pseudo class' do
|
||||
parse_css(':empty').should == parse_xpath(
|
||||
'descendant-or-self::*[not(node())]'
|
||||
)
|
||||
parse_css(':empty').should == parse_xpath('descendant::*[not(node())]')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ describe Oga::CSS::Parser do
|
|||
context ':first-child pseudo class' do
|
||||
example 'parse the :first-child pseudo class' do
|
||||
parse_css(':first-child').should == parse_xpath(
|
||||
'descendant-or-self::*[count(preceding-sibling::*) = 0]'
|
||||
'descendant::*[count(preceding-sibling::*) = 0]'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ describe Oga::CSS::Parser do
|
|||
context ':first-of-type pseudo class' do
|
||||
example 'parse the :first-of-type pseudo class' do
|
||||
parse_css(':first-of-type').should == parse_xpath(
|
||||
'descendant-or-self::*[position() = 1]'
|
||||
'descendant::*[position() = 1]'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ describe Oga::CSS::Parser do
|
|||
context ':last-child pseudo class' do
|
||||
example 'parse the :last-child pseudo class' do
|
||||
parse_css(':last-child').should == parse_xpath(
|
||||
'descendant-or-self::*[count(following-sibling::*) = 0]'
|
||||
'descendant::*[count(following-sibling::*) = 0]'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ describe Oga::CSS::Parser do
|
|||
context ':last-of-type pseudo class' do
|
||||
example 'parse the :last-of-type pseudo class' do
|
||||
parse_css(':last-of-type').should == parse_xpath(
|
||||
'descendant-or-self::*[position() = last()]'
|
||||
'descendant::*[position() = last()]'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,57 +4,57 @@ describe Oga::CSS::Parser do
|
|||
context ':nth-child pseudo class' do
|
||||
example 'parse the x:nth-child(1) pseudo class' do
|
||||
parse_css('x:nth-child(1)').should == parse_xpath(
|
||||
'descendant-or-self::x[count(preceding-sibling::*) = 0]'
|
||||
'descendant::x[count(preceding-sibling::*) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-child(1) pseudo class' do
|
||||
parse_css(':nth-child(1)').should == parse_xpath(
|
||||
'descendant-or-self::*[count(preceding-sibling::*) = 0]'
|
||||
'descendant::*[count(preceding-sibling::*) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-child(2) pseudo class' do
|
||||
parse_css(':nth-child(2)').should == parse_xpath(
|
||||
'descendant-or-self::*[count(preceding-sibling::*) = 1]'
|
||||
'descendant::*[count(preceding-sibling::*) = 1]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the x:nth-child(even) pseudo class' do
|
||||
parse_css('x:nth-child(even)').should == parse_xpath(
|
||||
'descendant-or-self::x[((count(preceding-sibling::*) + 1) mod 2) = 0]'
|
||||
'descendant::x[((count(preceding-sibling::*) + 1) mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
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 ' \
|
||||
'descendant::x[(count(preceding-sibling::*) + 1) >= 1 ' \
|
||||
'and (((count(preceding-sibling::*) + 1) - 1) mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the x:nth-child(n) pseudo class' do
|
||||
parse_css('x:nth-child(n)').should == parse_xpath(
|
||||
'descendant-or-self::x[((count(preceding-sibling::*) + 1) mod 1) = 0]'
|
||||
'descendant::x[((count(preceding-sibling::*) + 1) mod 1) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the x:nth-child(-n) pseudo class' do
|
||||
parse_css('x:nth-child(-n)').should == parse_xpath(
|
||||
'descendant-or-self::x[((count(preceding-sibling::*) + 1) mod 1) = 0]'
|
||||
'descendant::x[((count(preceding-sibling::*) + 1) mod 1) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the x:nth-child(-n+6) pseudo class' do
|
||||
parse_css('x:nth-child(-n+6)').should == parse_xpath(
|
||||
'descendant-or-self::x[((count(preceding-sibling::*) + 1) <= 6) ' \
|
||||
'descendant::x[((count(preceding-sibling::*) + 1) <= 6) ' \
|
||||
'and (((count(preceding-sibling::*) + 1) - 6) mod 1) = 0]'
|
||||
)
|
||||
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 ' \
|
||||
'descendant::x[(count(preceding-sibling::*) + 1) >= 5 ' \
|
||||
'and (((count(preceding-sibling::*) + 1) - 5) mod 1) = 0]'
|
||||
)
|
||||
end
|
||||
|
@ -65,28 +65,28 @@ describe Oga::CSS::Parser do
|
|||
|
||||
example 'parse the x:nth-child(2n+1) pseudo class' do
|
||||
parse_css('x:nth-child(2n+1)').should == parse_xpath(
|
||||
'descendant-or-self::x[(count(preceding-sibling::*) + 1) >= 1 ' \
|
||||
'descendant::x[(count(preceding-sibling::*) + 1) >= 1 ' \
|
||||
'and (((count(preceding-sibling::*) + 1) - 1) mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the x:nth-child(3n+1) pseudo class' do
|
||||
parse_css('x:nth-child(3n+1)').should == parse_xpath(
|
||||
'descendant-or-self::x[(count(preceding-sibling::*) + 1) >= 1 ' \
|
||||
'descendant::x[(count(preceding-sibling::*) + 1) >= 1 ' \
|
||||
'and (((count(preceding-sibling::*) + 1) - 1) mod 3) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the x:nth-child(2n-6) pseudo class' do
|
||||
parse_css('x:nth-child(2n-6)').should == parse_xpath(
|
||||
'descendant-or-self::x[(count(preceding-sibling::*) + 1) >= 2 ' \
|
||||
'descendant::x[(count(preceding-sibling::*) + 1) >= 2 ' \
|
||||
'and (((count(preceding-sibling::*) + 1) - 2) mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the x:nth-child(-2n+6) pseudo class' do
|
||||
parse_css('x:nth-child(-2n+6)').should == parse_xpath(
|
||||
'descendant-or-self::x[((count(preceding-sibling::*) + 1) <= 6) ' \
|
||||
'descendant::x[((count(preceding-sibling::*) + 1) <= 6) ' \
|
||||
'and (((count(preceding-sibling::*) + 1) - 6) mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
|
|
@ -4,50 +4,50 @@ 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]'
|
||||
'descendant::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]'
|
||||
'descendant::*[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]'
|
||||
'descendant::*[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]'
|
||||
'descendant::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 ' \
|
||||
'descendant::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]'
|
||||
'descendant::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]'
|
||||
'descendant::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) ' \
|
||||
'descendant::x[((count(following-sibling::*) + 1) <= 6) ' \
|
||||
'and (((count(following-sibling::*) + 1) - 6) mod 1) = 0]'
|
||||
)
|
||||
end
|
||||
|
@ -60,28 +60,28 @@ describe Oga::CSS::Parser do
|
|||
|
||||
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 ' \
|
||||
'descendant::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 ' \
|
||||
'descendant::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) ' \
|
||||
'descendant::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) ' \
|
||||
'descendant::x[((count(following-sibling::*) + 1) <= 6) ' \
|
||||
'and (((count(following-sibling::*) + 1) - 6) mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
|
|
@ -4,106 +4,106 @@ describe Oga::CSS::Parser do
|
|||
context ':nth-last-of-type pseudo class' do
|
||||
example 'parse the :nth-last-of-type(1) pseudo class' do
|
||||
parse_css(':nth-last-of-type(1)').should == parse_xpath(
|
||||
'descendant-or-self::*[(last() - position() + 1) = 1]'
|
||||
'descendant::*[(last() - position() + 1) = 1]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(2n) pseudo class' do
|
||||
parse_css(':nth-last-of-type(2n)').should == parse_xpath(
|
||||
'descendant-or-self::*[((last() - position() + 1) mod 2) = 0]'
|
||||
'descendant::*[((last() - position() + 1) mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(3n) pseudo class' do
|
||||
parse_css(':nth-last-of-type(3n)').should == parse_xpath(
|
||||
'descendant-or-self::*[((last() - position() + 1) mod 3) = 0]'
|
||||
'descendant::*[((last() - position() + 1) mod 3) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(2n+5) pseudo class' do
|
||||
parse_css(':nth-last-of-type(2n+5)').should == parse_xpath(
|
||||
'descendant-or-self::*[((last() - position() + 1) >= 5) ' \
|
||||
'descendant::*[((last() - position() + 1) >= 5) ' \
|
||||
'and ((((last() - position() + 1) - 5) mod 2) = 0)]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(3n+5) pseudo class' do
|
||||
parse_css(':nth-last-of-type(3n+5)').should == parse_xpath(
|
||||
'descendant-or-self::*[((last() - position() + 1) >= 5) ' \
|
||||
'descendant::*[((last() - position() + 1) >= 5) ' \
|
||||
'and ((((last() - position() + 1) - 5) mod 3) = 0)]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(2n-5) pseudo class' do
|
||||
parse_css(':nth-last-of-type(2n-5)').should == parse_xpath(
|
||||
'descendant-or-self::*[((last() - position() + 1) >= 1) ' \
|
||||
'descendant::*[((last() - position() + 1) >= 1) ' \
|
||||
'and ((((last() - position() + 1) - 1) mod 2) = 0)]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(2n-6) pseudo class' do
|
||||
parse_css(':nth-last-of-type(2n-6)').should == parse_xpath(
|
||||
'descendant-or-self::*[((last() - position() + 1) >= 2) ' \
|
||||
'descendant::*[((last() - position() + 1) >= 2) ' \
|
||||
'and ((((last() - position() + 1) - 2) mod 2) = 0)]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(-2n+5) pseudo class' do
|
||||
parse_css(':nth-last-of-type(-2n+5)').should == parse_xpath(
|
||||
'descendant-or-self::*[((last() - position() + 1) <= 5) ' \
|
||||
'descendant::*[((last() - position() + 1) <= 5) ' \
|
||||
'and (((last() - position() + 1) - 5) mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(-2n-5) pseudo class' do
|
||||
parse_css(':nth-last-of-type(-2n-5)').should == parse_xpath(
|
||||
'descendant-or-self::*[((last() - position() + 1) <= -1) ' \
|
||||
'descendant::*[((last() - position() + 1) <= -1) ' \
|
||||
'and (((last() - position() + 1) - -1) mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(-2n-6) pseudo class' do
|
||||
parse_css(':nth-last-of-type(-2n-6)').should == parse_xpath(
|
||||
'descendant-or-self::*[((last() - position() + 1) <= -2) ' \
|
||||
'descendant::*[((last() - position() + 1) <= -2) ' \
|
||||
'and (((last() - position() + 1) - -2) mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(even) pseudo class' do
|
||||
parse_css(':nth-last-of-type(even)').should == parse_xpath(
|
||||
'descendant-or-self::*[((last() - position() + 1) mod 2) = 0]'
|
||||
'descendant::*[((last() - position() + 1) mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(odd) pseudo class' do
|
||||
parse_css(':nth-last-of-type(odd)').should == parse_xpath(
|
||||
'descendant-or-self::*[((last() - position() + 1) >= 1) ' \
|
||||
'descendant::*[((last() - position() + 1) >= 1) ' \
|
||||
'and ((((last() - position() + 1) - 1) mod 2) = 0)]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(n) pseudo class' do
|
||||
parse_css(':nth-last-of-type(n)').should == parse_xpath(
|
||||
'descendant-or-self::*[((last() - position() + 1) mod 1) = 0]'
|
||||
'descendant::*[((last() - position() + 1) mod 1) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(n+5) pseudo class' do
|
||||
parse_css(':nth-last-of-type(n+5)').should == parse_xpath(
|
||||
'descendant-or-self::*[(last() - position() + 1) >= 5 ' \
|
||||
'descendant::*[(last() - position() + 1) >= 5 ' \
|
||||
'and (((last() - position() + 1) - 5) mod 1) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(-n) pseudo class' do
|
||||
parse_css(':nth-last-of-type(-n)').should == parse_xpath(
|
||||
'descendant-or-self::*[((last() - position() + 1) mod 1) = 0]'
|
||||
'descendant::*[((last() - position() + 1) mod 1) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-last-of-type(-n+5) pseudo class' do
|
||||
parse_css(':nth-last-of-type(-n+5)').should == parse_xpath(
|
||||
'descendant-or-self::*[((last() - position() + 1) <= 5) ' \
|
||||
'descendant::*[((last() - position() + 1) <= 5) ' \
|
||||
'and (((last() - position() + 1) - 5) mod 1) = 0]'
|
||||
)
|
||||
end
|
||||
|
|
|
@ -4,106 +4,106 @@ describe Oga::CSS::Parser do
|
|||
context ':nth-of-type pseudo class' do
|
||||
example 'parse the :nth-of-type(1) pseudo class' do
|
||||
parse_css(':nth-of-type(1)').should == parse_xpath(
|
||||
'descendant-or-self::*[position() = 1]'
|
||||
'descendant::*[position() = 1]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(2n) pseudo class' do
|
||||
parse_css(':nth-of-type(2n)').should == parse_xpath(
|
||||
'descendant-or-self::*[(position() mod 2) = 0]'
|
||||
'descendant::*[(position() mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(3n) pseudo class' do
|
||||
parse_css(':nth-of-type(3n)').should == parse_xpath(
|
||||
'descendant-or-self::*[(position() mod 3) = 0]'
|
||||
'descendant::*[(position() mod 3) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(2n+5) pseudo class' do
|
||||
parse_css(':nth-of-type(2n+5)').should == parse_xpath(
|
||||
'descendant-or-self::*[(position() >= 5) ' \
|
||||
'descendant::*[(position() >= 5) ' \
|
||||
'and (((position() - 5) mod 2) = 0)]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(3n+5) pseudo class' do
|
||||
parse_css(':nth-of-type(3n+5)').should == parse_xpath(
|
||||
'descendant-or-self::*[(position() >= 5) ' \
|
||||
'descendant::*[(position() >= 5) ' \
|
||||
'and (((position() - 5) mod 3) = 0)]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(2n-5) pseudo class' do
|
||||
parse_css(':nth-of-type(2n-5)').should == parse_xpath(
|
||||
'descendant-or-self::*[(position() >= 1) ' \
|
||||
'descendant::*[(position() >= 1) ' \
|
||||
'and (((position() - 1) mod 2) = 0)]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(2n-6) pseudo class' do
|
||||
parse_css(':nth-of-type(2n-6)').should == parse_xpath(
|
||||
'descendant-or-self::*[(position() >= 2) ' \
|
||||
'descendant::*[(position() >= 2) ' \
|
||||
'and (((position() - 2) mod 2) = 0)]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(-2n+5) pseudo class' do
|
||||
parse_css(':nth-of-type(-2n+5)').should == parse_xpath(
|
||||
'descendant-or-self::*[(position() <= 5) ' \
|
||||
'descendant::*[(position() <= 5) ' \
|
||||
'and ((position() - 5) mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(-2n-5) pseudo class' do
|
||||
parse_css(':nth-of-type(-2n-5)').should == parse_xpath(
|
||||
'descendant-or-self::*[(position() <= -1) ' \
|
||||
'descendant::*[(position() <= -1) ' \
|
||||
'and ((position() - -1) mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(-2n-6) pseudo class' do
|
||||
parse_css(':nth-of-type(-2n-6)').should == parse_xpath(
|
||||
'descendant-or-self::*[(position() <= -2) ' \
|
||||
'descendant::*[(position() <= -2) ' \
|
||||
'and ((position() - -2) mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(even) pseudo class' do
|
||||
parse_css(':nth-of-type(even)').should == parse_xpath(
|
||||
'descendant-or-self::*[(position() mod 2) = 0]'
|
||||
'descendant::*[(position() mod 2) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(odd) pseudo class' do
|
||||
parse_css(':nth-of-type(odd)').should == parse_xpath(
|
||||
'descendant-or-self::*[(position() >= 1) ' \
|
||||
'descendant::*[(position() >= 1) ' \
|
||||
'and (((position() - 1) mod 2) = 0)]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(n) pseudo class' do
|
||||
parse_css(':nth-of-type(n)').should == parse_xpath(
|
||||
'descendant-or-self::*[(position() mod 1) =0]'
|
||||
'descendant::*[(position() mod 1) =0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(n+5) pseudo class' do
|
||||
parse_css(':nth-of-type(n+5)').should == parse_xpath(
|
||||
'descendant-or-self::*[position() >= 5 ' \
|
||||
'descendant::*[position() >= 5 ' \
|
||||
'and ((position() - 5) mod 1) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(-n) pseudo class' do
|
||||
parse_css(':nth-of-type(-n)').should == parse_xpath(
|
||||
'descendant-or-self::*[(position() mod 1) = 0]'
|
||||
'descendant::*[(position() mod 1) = 0]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the :nth-of-type(-n+5) pseudo class' do
|
||||
parse_css(':nth-of-type(-n+5)').should == parse_xpath(
|
||||
'descendant-or-self::*[(position() <= 5) ' \
|
||||
'descendant::*[(position() <= 5) ' \
|
||||
'and ((position() - 5) mod 1) = 0]'
|
||||
)
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ describe Oga::CSS::Parser do
|
|||
context ':only-child pseudo class' do
|
||||
example 'parse the :only-child pseudo class' do
|
||||
parse_css(':only-child').should == parse_xpath(
|
||||
'descendant-or-self::*[count(preceding-sibling::*) = 0 ' \
|
||||
'descendant::*[count(preceding-sibling::*) = 0 ' \
|
||||
'and count(following-sibling::*) = 0]'
|
||||
)
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ describe Oga::CSS::Parser do
|
|||
context ':only-of-type pseudo class' do
|
||||
example 'parse the :only-of-type pseudo class' do
|
||||
parse_css(':only-of-type').should == parse_xpath(
|
||||
'descendant-or-self::*[last() = 1]'
|
||||
'descendant::*[last() = 1]'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,15 +3,11 @@ require 'spec_helper'
|
|||
describe Oga::CSS::Parser do
|
||||
context ':root pseudo class' do
|
||||
example 'parse the x:root pseudo class' do
|
||||
parse_css('x:root').should == parse_xpath(
|
||||
'descendant-or-self::x[not(parent::*)]'
|
||||
)
|
||||
parse_css('x:root').should == parse_xpath('descendant::x[not(parent::*)]')
|
||||
end
|
||||
|
||||
example 'parse the :root pseudo class' do
|
||||
parse_css(':root').should == parse_xpath(
|
||||
'descendant-or-self::*[not(parent::*)]'
|
||||
)
|
||||
parse_css(':root').should == parse_xpath('descendant::*[not(parent::*)]')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,15 +3,15 @@ require 'spec_helper'
|
|||
describe Oga::CSS::Parser do
|
||||
context 'wildcards' do
|
||||
example 'parse a wildcard name test' do
|
||||
parse_css('*').should == parse_xpath('descendant-or-self::*')
|
||||
parse_css('*').should == parse_xpath('descendant::*')
|
||||
end
|
||||
|
||||
example 'parse a wildcard namespace test' do
|
||||
parse_css('*|foo').should == parse_xpath('descendant-or-self::*:foo')
|
||||
parse_css('*|foo').should == parse_xpath('descendant::*:foo')
|
||||
end
|
||||
|
||||
example 'parse a wildcard namespace and name test' do
|
||||
parse_css('*|*').should == parse_xpath('descendant-or-self::*:*')
|
||||
parse_css('*|*').should == parse_xpath('descendant::*:*')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue