changeset 1660:3accd3e00cd2

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
author Johannes Hofmann <Johannes.Hofmann@gmx.de>
date Fri, 23 Apr 2010 14:53:33 +0200
parents 0cf0c7e0064c
children 1a88fc9331c8
files src/css.cc src/css.hh
diffstat 2 files changed, 18 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/css.cc	Thu Apr 22 02:21:38 2010 +0000
+++ b/src/css.cc	Fri Apr 23 14:53:33 2010 +0200
@@ -287,13 +287,14 @@
    }
 }
 
-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 @@
    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::userImportantStyle;
 
 CssContext::CssContext () {
+   pos = 0;
+
    for (int o = CSS_PRIMARY_USER_AGENT; o < CSS_PRIMARY_LAST; o++)
       sheet[o] = NULL;
 
@@ -532,7 +541,7 @@
                           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 ();
--- a/src/css.hh	Thu Apr 22 02:21:38 2010 +0000
+++ b/src/css.hh	Fri Apr 23 14:53:33 2010 +0200
@@ -407,17 +407,18 @@
 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 @@
       static CssStyleSheet *userStyle;
       static CssStyleSheet *userImportantStyle;
       CssStyleSheet *sheet[CSS_PRIMARY_USER_IMPORTANT + 1];
+      int pos; 
 
       void buildUserAgentStyle ();
       void buildUserStyle ();