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])) }
|
||||
;
|
||||
|
||||
# The AST of these operators is mostly based on what
|
||||
# `Nokogiri::CSS.xpath_for('...')` returns.
|
||||
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
|
||||
|
|
|
@ -3,56 +3,40 @@ require 'spec_helper'
|
|||
describe Oga::CSS::Parser do
|
||||
context 'operators' do
|
||||
example 'parse the = operator' do
|
||||
parse_css('x[a="b"]').should == s(
|
||||
:test,
|
||||
nil,
|
||||
'x',
|
||||
s(:eq, s(:test, nil, 'a'), s(:string, 'b'))
|
||||
parse_css('x[a="b"]').should == parse_xpath(
|
||||
'descendant-or-self::x[@a="b"]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the ~= operator' do
|
||||
parse_css('x[a~="b"]').should == s(
|
||||
:test,
|
||||
nil,
|
||||
'x',
|
||||
s(:space_in, s(:test, nil, 'a'), s(:string, 'b'))
|
||||
parse_css('x[a~="b"]').should == parse_xpath(
|
||||
'descendant-or-self::x[contains(concat(" ", @a, " "), ' \
|
||||
'concat(" ", "b", " "))]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the ^= operator' do
|
||||
parse_css('x[a^="b"]').should == s(
|
||||
:test,
|
||||
nil,
|
||||
'x',
|
||||
s(:starts_with, s(:test, nil, 'a'), s(:string, 'b'))
|
||||
parse_css('x[a^="b"]').should == parse_xpath(
|
||||
'descendant-or-self::x[starts-with(@a, "b")]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the $= operator' do
|
||||
parse_css('x[a$="b"]').should == s(
|
||||
:test,
|
||||
nil,
|
||||
'x',
|
||||
s(:ends_with, s(:test, nil, 'a'), s(:string, 'b'))
|
||||
parse_css('x[a$="b"]').should == parse_xpath(
|
||||
'descendant-or-self::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 == s(
|
||||
:test,
|
||||
nil,
|
||||
'x',
|
||||
s(:in, s(:test, nil, 'a'), s(:string, 'b'))
|
||||
parse_css('x[a*="b"]').should == parse_xpath(
|
||||
'descendant-or-self::x[contains(@a, "b")]'
|
||||
)
|
||||
end
|
||||
|
||||
example 'parse the |= operator' do
|
||||
parse_css('x[a|="b"]').should == s(
|
||||
:test,
|
||||
nil,
|
||||
'x',
|
||||
s(:hyphen_in, s(:test, nil, 'a'), s(:string, 'b'))
|
||||
parse_css('x[a|="b"]').should == parse_xpath(
|
||||
'descendant-or-self::x[@a = "b" or starts-with(@a, concat("b", "-"))]'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue