Proper parsing support for all CSS operators.
This commit is contained in:
parent
24ae791f00
commit
32764c9a14
|
|
@ -138,8 +138,76 @@ rule
|
||||||
: node_name { s(:axis, 'attribute', s(:test, *val[0])) }
|
: node_name { s(:axis, 'attribute', s(:test, *val[0])) }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
# The AST of these operators is mostly based on what
|
||||||
|
# `Nokogiri::CSS.xpath_for('...')` returns.
|
||||||
operator
|
operator
|
||||||
: attribute T_EQ string { s(:eq, val[0], val[2]) }
|
# a="b"
|
||||||
|
: attribute T_EQ string
|
||||||
|
{
|
||||||
|
s(:eq, val[0], val[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
# a~="b"
|
||||||
|
| attribute T_SPACE_IN string
|
||||||
|
{
|
||||||
|
s(
|
||||||
|
:call,
|
||||||
|
'contains',
|
||||||
|
s(:call, 'concat', s(:string, ' '), val[0], s(:string, ' ')),
|
||||||
|
s(:call, 'concat', s(:string, ' '), val[2], s(:string, ' '))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# a^="b"
|
||||||
|
| attribute T_STARTS_WITH string
|
||||||
|
{
|
||||||
|
s(:call, 'starts-with', val[0], val[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
# a$="b"
|
||||||
|
| attribute T_ENDS_WITH string
|
||||||
|
{
|
||||||
|
s(
|
||||||
|
:eq,
|
||||||
|
s(
|
||||||
|
:call,
|
||||||
|
'substring',
|
||||||
|
val[0],
|
||||||
|
s(
|
||||||
|
:add,
|
||||||
|
s(
|
||||||
|
:sub,
|
||||||
|
s(:call, 'string-length', val[0]),
|
||||||
|
s(:call, 'string-length', val[2])
|
||||||
|
),
|
||||||
|
s(:int, 1)
|
||||||
|
),
|
||||||
|
s(:call, 'string-length', val[2])
|
||||||
|
),
|
||||||
|
val[2]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# a*="b"
|
||||||
|
| attribute T_IN string
|
||||||
|
{
|
||||||
|
s(:call, 'contains', val[0], val[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
# a|="b"
|
||||||
|
| attribute T_HYPHEN_IN string
|
||||||
|
{
|
||||||
|
s(
|
||||||
|
:or,
|
||||||
|
s(:eq, val[0], val[2]),
|
||||||
|
s(
|
||||||
|
:call,
|
||||||
|
'starts-with',
|
||||||
|
val[0],
|
||||||
|
s(:call, 'concat', val[2], s(:string, '-'))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
class
|
class
|
||||||
|
|
|
||||||
|
|
@ -3,56 +3,40 @@ require 'spec_helper'
|
||||||
describe Oga::CSS::Parser do
|
describe Oga::CSS::Parser do
|
||||||
context 'operators' do
|
context 'operators' do
|
||||||
example 'parse the = operator' do
|
example 'parse the = operator' do
|
||||||
parse_css('x[a="b"]').should == s(
|
parse_css('x[a="b"]').should == parse_xpath(
|
||||||
:test,
|
'descendant-or-self::x[@a="b"]'
|
||||||
nil,
|
|
||||||
'x',
|
|
||||||
s(:eq, s(:test, nil, 'a'), s(:string, 'b'))
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the ~= operator' do
|
example 'parse the ~= operator' do
|
||||||
parse_css('x[a~="b"]').should == s(
|
parse_css('x[a~="b"]').should == parse_xpath(
|
||||||
:test,
|
'descendant-or-self::x[contains(concat(" ", @a, " "), ' \
|
||||||
nil,
|
'concat(" ", "b", " "))]'
|
||||||
'x',
|
|
||||||
s(:space_in, s(:test, nil, 'a'), s(:string, 'b'))
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the ^= operator' do
|
example 'parse the ^= operator' do
|
||||||
parse_css('x[a^="b"]').should == s(
|
parse_css('x[a^="b"]').should == parse_xpath(
|
||||||
:test,
|
'descendant-or-self::x[starts-with(@a, "b")]'
|
||||||
nil,
|
|
||||||
'x',
|
|
||||||
s(:starts_with, s(:test, nil, 'a'), s(:string, 'b'))
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the $= operator' do
|
example 'parse the $= operator' do
|
||||||
parse_css('x[a$="b"]').should == s(
|
parse_css('x[a$="b"]').should == parse_xpath(
|
||||||
:test,
|
'descendant-or-self::x[substring(@a, string-length(@a) - ' \
|
||||||
nil,
|
'string-length("b") + 1, string-length("b")) = "b"]'
|
||||||
'x',
|
|
||||||
s(:ends_with, s(:test, nil, 'a'), s(:string, 'b'))
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the *= operator' do
|
example 'parse the *= operator' do
|
||||||
parse_css('x[a*="b"]').should == s(
|
parse_css('x[a*="b"]').should == parse_xpath(
|
||||||
:test,
|
'descendant-or-self::x[contains(@a, "b")]'
|
||||||
nil,
|
|
||||||
'x',
|
|
||||||
s(:in, s(:test, nil, 'a'), s(:string, 'b'))
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'parse the |= operator' do
|
example 'parse the |= operator' do
|
||||||
parse_css('x[a|="b"]').should == s(
|
parse_css('x[a|="b"]').should == parse_xpath(
|
||||||
:test,
|
'descendant-or-self::x[@a = "b" or starts-with(@a, concat("b", "-"))]'
|
||||||
nil,
|
|
||||||
'x',
|
|
||||||
s(:hyphen_in, s(:test, nil, 'a'), s(:string, 'b'))
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue