Changeset 2831:580cb3f32382 in livinglogic.python.xist

Show
Ignore:
Timestamp:
07/31/07 15:16:29 (12 years ago)
Author:
Walter Doerwald <walter@…>
Branch:
default
Message:

Add a method cssweight() to all selectors.

This methods calculates the specificity of an CSS selector as specified
here: http://www.w3.org/TR/css3-selectors/#specificity

Files:
2 modified

Legend:

Unmodified
Added
Removed
  • src/ll/xist/xfind.py

    r2830 r2831  
    8686 
    8787 
     88class CSSWeight(tuple): 
     89    """ 
     90    The specificity of a &CSS; selector as a 3-item tuple as specified by 
     91    <link href="http://www.w3.org/TR/css3-selectors/#specificity">CSS3</link>. 
     92    """ 
     93 
     94    def __new__(cls, a=0, b=0, c=0): 
     95        return tuple.__new__(cls, (a, b, c)) 
     96 
     97    def __add__(self, other): 
     98        return CSSWeight(self[0]+other[0], self[1]+other[1], self[2]+other[2]) 
     99 
     100    def __repr__(self): 
     101        return "CSSWeight(%r, %r, %r)" % (self[0], self[1], self[2]) 
     102 
     103 
    88104class Selector(xsc.WalkFilter): 
    89105    """ 
     
    121137    def __invert__(self): 
    122138        return NotCombinator(self) 
     139 
     140    def cssweight(self): 
     141        """ 
     142        Return the &CSS; specificity of <self/> as a 
     143        <pyref class="CSSWeight"><class>CSSWeight</class></pyref> object. 
     144        """ 
     145        return CSSWeight() 
    123146 
    124147 
     
    731754        return "%s(%r)" % (self.__class__.__name__, self.id) 
    732755 
     756    def cssweight(self): 
     757        return CSSWeight(1, 0, 0) 
     758 
    733759 
    734760class hasclass(Selector): 
     
    766792    def __str__(self): 
    767793        return "%s(%r)" % (self.__class__.__name__, self.classname) 
     794 
     795    def cssweight(self): 
     796        return CSSWeight(0, 1, 0) 
    768797 
    769798 
     
    821850            right = "(%s)" % right 
    822851        return "%s%s%s" % (left, self.symbol, right) 
     852 
     853    def cssweight(self): 
     854        return self.left.cssweight()+self.right.cssweight() 
    823855 
    824856 
     
    10041036            v.append(s) 
    10051037        return self.symbol.join(v) 
     1038 
     1039    def cssweight(self): 
     1040        raise TypeError("no weight info for chained combinator") 
    10061041 
    10071042 
     
    12741309### 
    12751310 
    1276 class CSSHasAttributeSelector(Selector): 
     1311class CSSWeightedSelector(Selector): 
     1312    def cssweight(self): 
     1313        return CSSWeight(0, 1, 0) 
     1314 
     1315 
     1316class CSSHasAttributeSelector(CSSWeightedSelector): 
    12771317    def __init__(self, attributename): 
    12781318        self.attributename = attributename 
     
    12891329 
    12901330 
    1291 class CSSAttributeListSelector(Selector): 
     1331class CSSAttributeListSelector(CSSWeightedSelector): 
    12921332    def __init__(self, attributename, attributevalue): 
    12931333        self.attributename = attributename 
     
    13061346 
    13071347 
    1308 class CSSAttributeLangSelector(Selector): 
     1348class CSSAttributeLangSelector(CSSWeightedSelector): 
    13091349    def __init__(self, attributename, attributevalue): 
    13101350        self.attributename = attributename 
     
    13251365 
    13261366 
    1327 class CSSFirstChildSelector(Selector): 
     1367class CSSFirstChildSelector(CSSWeightedSelector): 
    13281368    def match(self, path): 
    13291369        return len(path) >= 2 and _is_nth_node(path[-2][xsc.Element], path[-1], 1) 
     
    13331373 
    13341374 
    1335 class CSSLastChildSelector(Selector): 
     1375class CSSLastChildSelector(CSSWeightedSelector): 
    13361376    def match(self, path): 
    13371377        return len(path) >= 2 and _is_nth_last_node(path[-2][xsc.Element], path[-1], 1) 
     
    13411381 
    13421382 
    1343 class CSSFirstOfTypeSelector(Selector): 
     1383class CSSFirstOfTypeSelector(CSSWeightedSelector): 
    13441384    def match(self, path): 
    13451385        if len(path) >= 2: 
     
    13521392 
    13531393 
    1354 class CSSLastOfTypeSelector(Selector): 
     1394class CSSLastOfTypeSelector(CSSWeightedSelector): 
    13551395    def match(self, path): 
    13561396        if len(path) >= 2: 
     
    13631403 
    13641404 
    1365 class CSSOnlyChildSelector(Selector): 
     1405class CSSOnlyChildSelector(CSSWeightedSelector): 
    13661406    def match(self, path): 
    13671407        if len(path) >= 2: 
     
    13781418 
    13791419 
    1380 class CSSOnlyOfTypeSelector(Selector): 
     1420class CSSOnlyOfTypeSelector(CSSWeightedSelector): 
    13811421    def match(self, path): 
    13821422        if len(path) >= 2: 
     
    13931433 
    13941434 
    1395 class CSSEmptySelector(Selector): 
     1435class CSSEmptySelector(CSSWeightedSelector): 
    13961436    def match(self, path): 
    13971437        if path: 
     
    14081448 
    14091449 
    1410 class CSSRootSelector(Selector): 
     1450class CSSRootSelector(CSSWeightedSelector): 
    14111451    def match(self, path): 
    14121452        return len(path) == 1 and isinstance(path[-1], xsc.Element) 
     
    14161456 
    14171457 
    1418 class CSSLinkSelector(Selector): 
     1458class CSSLinkSelector(CSSWeightedSelector): 
    14191459    def match(self, path): 
    14201460        if path: 
     
    14271467 
    14281468 
    1429 class CSSInvalidPseudoSelector(Selector): 
     1469class CSSInvalidPseudoSelector(CSSWeightedSelector): 
    14301470    def match(self, path): 
    14311471        return False 
     
    14471487 
    14481488 
    1449 class CSSFunctionSelector(Selector): 
     1489class CSSFunctionSelector(CSSWeightedSelector): 
    14501490    def __init__(self, value=None): 
    14511491        self.value = value 
     
    15221562        v.append(")") 
    15231563        return "".join(v) 
     1564 
     1565    def cssweight(self): 
     1566        result = CSSWeight(0, 0, int(self.type != "*")) 
     1567        for selector in self.selectors: 
     1568            result += selector.cssweight() 
     1569        return result 
    15241570 
    15251571 
  • test/test_xfind.py

    r2824 r2831  
    391391    assert list(e.walknode(xfind.css("em[class~='gurk']"))) == [e[0], e[1]] 
    392392    assert list(e.walknode(xfind.css("em[lang|='en']"))) == [e[0], e[1]] 
     393 
     394 
     395def test_cssweight(): 
     396    # from http://www.w3.org/TR/css3-selectors/#specificity 
     397    assert xfind.css("*").cssweight() == (0, 0, 0) 
     398    assert xfind.css("LI").cssweight() == (0, 0, 1) 
     399    assert xfind.css("UL LI").cssweight() == (0, 0, 2) 
     400    assert xfind.css("UL OL+LI").cssweight() == (0, 0, 3) 
     401    assert xfind.css("UL OL LI.red").cssweight() == (0, 1, 3) 
     402    assert xfind.css("LI.red.level").cssweight() == (0, 2, 1) 
     403    assert xfind.css("#x34y").cssweight() == (1, 0, 0) 
     404    # The following is not supported 
     405    # assert xfind.css("#s12:not(FOO)").cssweight() == (1, 0, 1)