Handle indirect sibling selector
Adds parsing and handling of the indirect sibling selector, this should mean we can at least parse all CSS3 selectors even if we do not yet support all of them. Also adds tests for previously added CSS3 selectors. Change-Id: I1ce9afb9466044a38bdec167affc21a87837e4a4 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>bb10
parent
f2922c80a4
commit
997fa05d90
|
|
@ -1867,12 +1867,15 @@ bool StyleSelector::selectorMatches(const Selector &selector, NodePtr node)
|
|||
do {
|
||||
match = basicSelectorMatches(sel, node);
|
||||
if (!match) {
|
||||
if (sel.relationToNext == BasicSelector::MatchNextSelectorIfParent
|
||||
|| i == selector.basicSelectors.count() - 1) // first element must always match!
|
||||
if (i == selector.basicSelectors.count() - 1) // first element must always match!
|
||||
break;
|
||||
if (sel.relationToNext != BasicSelector::MatchNextSelectorIfAncestor &&
|
||||
sel.relationToNext != BasicSelector::MatchNextSelectorIfIndirectAdjecent)
|
||||
break;
|
||||
}
|
||||
|
||||
if (match || sel.relationToNext != BasicSelector::MatchNextSelectorIfAncestor)
|
||||
if (match || (sel.relationToNext != BasicSelector::MatchNextSelectorIfAncestor &&
|
||||
sel.relationToNext != BasicSelector::MatchNextSelectorIfIndirectAdjecent))
|
||||
--i;
|
||||
|
||||
if (i < 0)
|
||||
|
|
@ -1885,16 +1888,18 @@ bool StyleSelector::selectorMatches(const Selector &selector, NodePtr node)
|
|||
NodePtr nextParent = parentNode(node);
|
||||
freeNode(node);
|
||||
node = nextParent;
|
||||
} else if (sel.relationToNext == BasicSelector::MatchNextSelectorIfPreceeds) {
|
||||
} else if (sel.relationToNext == BasicSelector::MatchNextSelectorIfDirectAdjecent
|
||||
|| sel.relationToNext == BasicSelector::MatchNextSelectorIfIndirectAdjecent) {
|
||||
NodePtr previousSibling = previousSiblingNode(node);
|
||||
freeNode(node);
|
||||
node = previousSibling;
|
||||
}
|
||||
}
|
||||
if (isNullNode(node)) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
} while (i >= 0 && (match || sel.relationToNext == BasicSelector::MatchNextSelectorIfAncestor));
|
||||
} while (i >= 0 && (match || sel.relationToNext == BasicSelector::MatchNextSelectorIfAncestor
|
||||
|| sel.relationToNext == BasicSelector::MatchNextSelectorIfIndirectAdjecent));
|
||||
|
||||
freeNode(node);
|
||||
|
||||
|
|
@ -2356,9 +2361,11 @@ bool Parser::parseCombinator(BasicSelector::Relation *relation)
|
|||
prev();
|
||||
}
|
||||
if (test(PLUS)) {
|
||||
*relation = BasicSelector::MatchNextSelectorIfPreceeds;
|
||||
*relation = BasicSelector::MatchNextSelectorIfDirectAdjecent;
|
||||
} else if (test(GREATER)) {
|
||||
*relation = BasicSelector::MatchNextSelectorIfParent;
|
||||
} else if (test(TILDE)) {
|
||||
*relation = BasicSelector::MatchNextSelectorIfIndirectAdjecent;
|
||||
}
|
||||
skipSpace();
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -561,7 +561,8 @@ struct BasicSelector
|
|||
NoRelation,
|
||||
MatchNextSelectorIfAncestor,
|
||||
MatchNextSelectorIfParent,
|
||||
MatchNextSelectorIfPreceeds
|
||||
MatchNextSelectorIfDirectAdjecent,
|
||||
MatchNextSelectorIfIndirectAdjecent,
|
||||
};
|
||||
|
||||
QString elementName;
|
||||
|
|
@ -690,6 +691,7 @@ enum TokenType {
|
|||
PLUS,
|
||||
GREATER,
|
||||
COMMA,
|
||||
TILDE,
|
||||
|
||||
STRING,
|
||||
INVALID,
|
||||
|
|
@ -789,7 +791,7 @@ public:
|
|||
inline bool testImport() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("import")); }
|
||||
inline bool testMedia() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("media")); }
|
||||
inline bool testPage() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("page")); }
|
||||
inline bool testCombinator() { return test(PLUS) || test(GREATER) || test(S); }
|
||||
inline bool testCombinator() { return test(PLUS) || test(GREATER) || test(TILDE) || test(S); }
|
||||
inline bool testProperty() { return test(IDENT); }
|
||||
bool testTerm();
|
||||
inline bool testExpr() { return testTerm(); }
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -120,6 +120,7 @@ static const char *tokenName(QCss::TokenType t)
|
|||
case QCss::PLUS: return "PLUS";
|
||||
case QCss::GREATER: return "GREATER";
|
||||
case QCss::COMMA: return "COMMA";
|
||||
case QCss::TILDE: return "TILDE";
|
||||
case QCss::STRING: return "STRING";
|
||||
case QCss::INVALID: return "INVALID";
|
||||
case QCss::IDENT: return "IDENT";
|
||||
|
|
@ -480,7 +481,7 @@ void tst_QCssParser::selector_data()
|
|||
QCss::BasicSelector basic;
|
||||
|
||||
basic.elementName = "p";
|
||||
basic.relationToNext = QCss::BasicSelector::MatchNextSelectorIfPreceeds;
|
||||
basic.relationToNext = QCss::BasicSelector::MatchNextSelectorIfDirectAdjecent;
|
||||
sel.basicSelectors << basic;
|
||||
|
||||
basic = QCss::BasicSelector();
|
||||
|
|
@ -572,14 +573,29 @@ void tst_QCssParser::selector_data()
|
|||
QCss::BasicSelector basic;
|
||||
|
||||
basic.elementName = "e";
|
||||
basic.relationToNext = QCss::BasicSelector::MatchNextSelectorIfPreceeds;
|
||||
basic.relationToNext = QCss::BasicSelector::MatchNextSelectorIfDirectAdjecent;
|
||||
sel.basicSelectors << basic;
|
||||
|
||||
basic.elementName = "f";
|
||||
basic.relationToNext = QCss::BasicSelector::NoRelation;
|
||||
sel.basicSelectors << basic;
|
||||
|
||||
QTest::newRow("precede") << QString("e + f") << sel;
|
||||
QTest::newRow("lastsibling") << QString("e + f") << sel;
|
||||
}
|
||||
|
||||
{
|
||||
QCss::Selector sel;
|
||||
QCss::BasicSelector basic;
|
||||
|
||||
basic.elementName = "e";
|
||||
basic.relationToNext = QCss::BasicSelector::MatchNextSelectorIfIndirectAdjecent;
|
||||
sel.basicSelectors << basic;
|
||||
|
||||
basic.elementName = "f";
|
||||
basic.relationToNext = QCss::BasicSelector::NoRelation;
|
||||
sel.basicSelectors << basic;
|
||||
|
||||
QTest::newRow("previoussibling") << QString("e ~ f") << sel;
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -985,11 +1001,20 @@ void tst_QCssParser::styleSelector_data()
|
|||
QTest::newRow("attrmatch") << true << QString("[foo=bar]") << QString("<p foo=\"bar\" />") << QString();
|
||||
QTest::newRow("noattrmatch") << false << QString("[foo=bar]") << QString("<p foo=\"xyz\" />") << QString();
|
||||
|
||||
QTest::newRow("contains") << true << QString("[foo~=bar]") << QString("<p foo=\"baz bleh bar\" />") << QString();
|
||||
QTest::newRow("notcontains") << false << QString("[foo~=bar]") << QString("<p foo=\"test\" />") << QString();
|
||||
QTest::newRow("includes") << true << QString("[foo~=bar]") << QString("<p foo=\"baz bleh bar\" />") << QString();
|
||||
QTest::newRow("notincludes") << false << QString("[foo~=bar]") << QString("<p foo=\"bazblehbar\" />") << QString();
|
||||
|
||||
QTest::newRow("beingswith") << true << QString("[foo|=bar]") << QString("<p foo=\"bar-bleh\" />") << QString();
|
||||
QTest::newRow("notbeingswith") << false << QString("[foo|=bar]") << QString("<p foo=\"bleh-bar\" />") << QString();
|
||||
QTest::newRow("dashmatch") << true << QString("[foo|=bar]") << QString("<p foo=\"bar-bleh\" />") << QString();
|
||||
QTest::newRow("nodashmatch") << false << QString("[foo|=bar]") << QString("<p foo=\"barbleh\" />") << QString();
|
||||
|
||||
QTest::newRow("beginswith") << true << QString("[foo^=bar]") << QString("<p foo=\"barbleh\" />") << QString();
|
||||
QTest::newRow("nobeginswith") << false << QString("[foo^=bar]") << QString("<p foo=\"blehbleh\" />") << QString();
|
||||
|
||||
QTest::newRow("endswith") << true << QString("[foo$=bar]") << QString("<p foo=\"barbar\" />") << QString();
|
||||
QTest::newRow("noendswith") << false << QString("[foo$=bar]") << QString("<p foo=\"blehbleh\" />") << QString();
|
||||
|
||||
QTest::newRow("contains") << true << QString("[foo*=bar]") << QString("<p foo=\"blehbarbleh\" />") << QString();
|
||||
QTest::newRow("nocontains") << false << QString("[foo*=bar]") << QString("<p foo=\"blehbleh\" />") << QString();
|
||||
|
||||
QTest::newRow("attr2") << true << QString("[bar=foo]") << QString("<p bleh=\"bar\" bar=\"foo\" />") << QString();
|
||||
|
||||
|
|
@ -1070,10 +1095,19 @@ void tst_QCssParser::styleSelector_data()
|
|||
<< QString("<p1 /><p2 />")
|
||||
<< QString("p2");
|
||||
|
||||
QTest::newRow("noprevioussibling") << false << QString("p2 + p1")
|
||||
QTest::newRow("notprevioussibling") << false << QString("p2 + p1")
|
||||
<< QString("<p1 /><p2 />")
|
||||
<< QString("p2");
|
||||
|
||||
QTest::newRow("anyprevioussibling") << true << QString("p1 ~ p3")
|
||||
<< QString("<p1 /><p2 /><p3 />")
|
||||
<< QString("p3");
|
||||
|
||||
QTest::newRow("noprevioussibling") << false << QString("p3 ~ p2")
|
||||
<< QString("<p1 /><p2 /><p3 />")
|
||||
<< QString("p3");
|
||||
|
||||
|
||||
QTest::newRow("ancestry_firstmismatch") << false << QString("parent child[foo=bar]")
|
||||
<< QString("<parent><child /></parent>")
|
||||
<< QString("parent/child");
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ LBRACE = {w}"{"
|
|||
PLUS = {w}"+"
|
||||
GREATER = {w}">"
|
||||
COMMA = {w}","
|
||||
TILDE= {w}"~"
|
||||
|
||||
STRING = {string}
|
||||
INVALID = {invalid}
|
||||
Loading…
Reference in New Issue