diff options
author | Johannes Hofmann <Johannes.Hofmann@gmx.de> | 2010-04-23 14:53:33 +0200 |
---|---|---|
committer | Johannes Hofmann <Johannes.Hofmann@gmx.de> | 2010-04-23 14:53:33 +0200 |
commit | 0b045d5fe5e9540ba22b2d441d4346fbd3646dd9 (patch) | |
tree | fdd30ece6f5c57c6c0fc380065db83ae2d2acd7d | |
parent | 1b40d6342a64924426642cc742849a8172e25fb2 (diff) |
use CSS rule position when specificity is equal
When two CSS rules have the same specificity make sure they are
applied in the order as they appear in the stylesheets (see [1]).
Testcase:
<html><head><style>
A:link {color: red}
A.foo {color: green}
</style></head><body>
<a class="foo" href=http://www.dillo.org>should be green</a>
</body></html>
Reported by: corvid
[1] http://www.w3.org/TR/CSS2/cascade.html#cascading-order
-rw-r--r-- | src/css.cc | 19 | ||||
-rw-r--r-- | src/css.hh | 6 |
2 files changed, 18 insertions, 7 deletions
@@ -287,13 +287,14 @@ void CssSimpleSelector::print () { } } -CssRule::CssRule (CssSelector *selector, CssPropertyList *props) { +CssRule::CssRule (CssSelector *selector, CssPropertyList *props, int pos) { assert (selector->size () > 0); this->selector = selector; this->selector->ref (); this->props = props; this->props->ref (); + this->pos = pos; spec = selector->specificity (); }; @@ -435,17 +436,23 @@ void CssStyleSheet::apply (CssPropertyList *props, if (ruleList[numLists]) numLists++; - // Apply potentially matching rules from ruleList[0-3] with - // ascending specificity. Each ruleList is sorted already. + // Apply potentially matching rules from ruleList[0-numLists] with + // ascending specificity. + // If specificity is equal, rules are applied in order of appearance. + // Each ruleList is sorted already. while (true) { int minSpec = 1 << 30; + int minPos = 1 << 30; int minSpecIndex = -1; for (int i = 0; i < numLists; i++) { if (ruleList[i] && ruleList[i]->size () > index[i] && - ruleList[i]->get(index[i])->specificity () < minSpec) { + (ruleList[i]->get(index[i])->specificity () < minSpec || + (ruleList[i]->get(index[i])->specificity () == minSpec && + ruleList[i]->get(index[i])->position () < minPos))) { minSpec = ruleList[i]->get(index[i])->specificity (); + minPos = ruleList[i]->get(index[i])->position (); minSpecIndex = i; } } @@ -465,6 +472,8 @@ CssStyleSheet *CssContext::userStyle; CssStyleSheet *CssContext::userImportantStyle; CssContext::CssContext () { + pos = 0; + for (int o = CSS_PRIMARY_USER_AGENT; o < CSS_PRIMARY_LAST; o++) sheet[o] = NULL; @@ -532,7 +541,7 @@ void CssContext::addRule (CssSelector *sel, CssPropertyList *props, CssPrimaryOrder order) { if (props->size () > 0) { - CssRule *rule = new CssRule (sel, props); + CssRule *rule = new CssRule (sel, props, pos++); if (sheet[order] == NULL) sheet[order] = new CssStyleSheet (); @@ -407,17 +407,18 @@ class CssSelector { class CssRule { private: CssPropertyList *props; - int spec; + int spec, pos; public: CssSelector *selector; - CssRule (CssSelector *selector, CssPropertyList *props); + CssRule (CssSelector *selector, CssPropertyList *props, int pos); ~CssRule (); void apply (CssPropertyList *props, Doctree *docTree, const DoctreeNode *node); inline int specificity () { return spec; }; + inline int position () { return pos; }; void print (); }; @@ -475,6 +476,7 @@ class CssContext { static CssStyleSheet *userStyle; static CssStyleSheet *userImportantStyle; CssStyleSheet *sheet[CSS_PRIMARY_USER_IMPORTANT + 1]; + int pos; void buildUserAgentStyle (); void buildUserStyle (); |