Changeset 2834:4479db3b566a in livinglogic.python.xist

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

Add media filtering to html.itercssrules(). Add function applycss().

itercssrules() only filters on the media attribute of the stylesheet itself
and doesn't check media rules in the stylesheet.

applycss() puts the resulting properties into style attributes of each
selected node. However style attributes on the nodes themselves currently
get overwritten.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • src/ll/xist/ns/html.py

    r2829 r2834  
    13771377    import cssutils 
    13781378    from cssutils import css, stylesheets 
    1379     from cssutils.css import cssstyledeclaration, cssvalue, csscomment, property as property_ 
     1379    from cssutils.css import cssstyledeclaration, cssvalue, csscomment 
    13801380except ImportError: 
    13811381    pass 
    13821382 
    13831383 
     1384def _isstyle(path): 
     1385    if path: 
     1386        node = path[-1] 
     1387        return (isinstance(node, style) and unicode(node.attrs.type) == "text/css") or (isinstance(node, link) and unicode(node.attrs.rel) == "stylesheet") 
     1388    return False 
     1389 
     1390 
    13841391class itercssrules(object_): 
    1385     def __init__(self, node, base=None): 
     1392    def __init__(self, node, base=None, media=None): 
    13861393        self.node = node 
    13871394        if base is not None: 
    13881395            base = url.URL(base) 
    13891396        self.base = base 
    1390  
    1391     def _isstyle(self, path): 
    1392         if path: 
    1393             node = path[-1] 
    1394             return (isinstance(node, style) and unicode(node.attrs.type) == "text/css") or (isinstance(node, link) and unicode(node.attrs.rel) == "stylesheet") 
    1395         return False 
     1397        self.media = media 
     1398 
    13961399 
    13971400    def _fixurl(self, rule, base): 
    1398         for proplist in rule.style.seq: 
    1399             if isinstance(proplist, property_._Property): 
    1400                 for prop in proplist: 
    1401                     for (i, value) in enumerate(prop.cssValue.seq): 
     1401        if base is not None: 
     1402            for proplist in rule.style.seq: 
     1403                if not isinstance(proplist, csscomment.CSSComment): 
     1404                    for prop in proplist: 
     1405                        newvalue = [] 
     1406                        for value in prop.cssValue.seq: 
    14021407                            if value.startswith("url(") and value.endswith(")"): 
    1403                                 if base is not None: 
    1404                                     value = "url(%s)" % (base/value[4:-1]) 
    1405                                 prop.cssValue.seq[i] = value 
     1408                                value = "url(%s)" % (base/value[4:-1]) 
     1409                            newvalue.append(value) 
     1410                        prop.cssValue = "".join(newvalue) 
    14061411 
    14071412    def _doimport(self, parentsheet, base): 
    1408         for rule in parentsheet.cssRules: 
    1409             if rule.type == css.CSSRule.IMPORT_RULE: 
    1410                 href = url.URL(rule.href) 
    1411                 if base is not None: 
    1412                     href = base/href 
    1413                 media = rule.media 
    1414                 with contextlib.closing(href.open("rb")) as r: 
    1415                     href = r.finalurl() 
    1416                     text = r.read() 
    1417                 sheet = css.CSSStyleSheet(href=str(href), media=media, parentStyleSheet=parentsheet) 
    1418                 sheet.cssText = text 
    1419                 for rule in self._doimport(sheet, href): 
     1413        media = self._getmedia(parentsheet) 
     1414        if self.media is None or self.media in media: 
     1415            for rule in parentsheet.cssRules: 
     1416                if rule.type == css.CSSRule.IMPORT_RULE: 
     1417                    href = url.URL(rule.href) 
     1418                    if base is not None: 
     1419                        href = base/href 
     1420                    media = rule.media 
     1421                    with contextlib.closing(href.open("rb")) as r: 
     1422                        href = r.finalurl() 
     1423                        text = r.read() 
     1424                    sheet = css.CSSStyleSheet(href=str(href), media=media, parentStyleSheet=parentsheet) 
     1425                    sheet.cssText = text 
     1426                    for rule in self._doimport(sheet, href): 
     1427                        yield rule 
     1428                elif rule.type == css.CSSRule.STYLE_RULE: 
     1429                    self._fixurl(rule, base) 
    14201430                    yield rule 
    1421             elif rule.type == css.CSSRule.STYLE_RULE: 
    1422                 self._fixurl(rule, base) 
    1423                 yield rule 
    14241431 
    14251432    def __getitem__(self, index): 
    14261433        return misc.item(self, index) 
    14271434 
     1435    def _getmedia(self, stylesheet): 
     1436        while stylesheet is not None: 
     1437            if stylesheet.media is not None: 
     1438                media = [m.strip() for m in stylesheet.media.split(",")] 
     1439                # FIXME: remove extensions: see http://www.w3.org/TR/css3-mediaqueries/#idx-media-descriptor-1 
     1440                return media 
     1441            stylesheet = stylesheet.parentStyleSheet 
     1442        return None 
     1443         
    14281444    def __iter__(self): 
    14291445        import cssutils 
    1430         for cssnode in self.node.walknode(self._isstyle): 
     1446        for cssnode in self.node.walknode(_isstyle): 
    14311447            if isinstance(cssnode, style): 
    14321448                stylesheet = cssutils.parseString(unicode(cssnode.content)) 
    14331449                if self.base is not None: 
    14341450                    stylesheet.href = str(self.base) 
     1451                if "media" in cssnode.attrs: 
     1452                    stylesheet.media = unicode(cssnode.attrs.media) 
    14351453                for rule in self._doimport(stylesheet, self.base): 
    14361454                    yield rule 
     
    14441462                    stylesheet = cssutils.parseString(unicode(s)) 
    14451463                    stylesheet.href = str(href) 
     1464                    if "media" in cssnode.attrs: 
     1465                        stylesheet.media = unicode(cssnode.attrs.media) 
    14461466                    for rule in self._doimport(stylesheet, href): 
    14471467                        yield rule 
     1468 
     1469 
     1470def _keyrule((name, (value, count))): 
     1471    return count 
     1472 
     1473 
     1474def applycss(node, base=None, media=None): 
     1475    rules = [] 
     1476    for rule in itercssrules(node, base=base, media=media): 
     1477        for selector in rule.selectorList: 
     1478            selector = xfind.css(selector) 
     1479            rules.append((selector.cssweight(), selector, rule)) 
     1480    rules.sort() 
     1481    for path in node.walk(xsc.Element): 
     1482        if path[-1].Attrs.isallowed("style"): 
     1483            styles = {} 
     1484            count = 0 
     1485            for (weight, selector, rule) in rules: 
     1486                if selector.match(path): 
     1487                    for prop in rule.style.seq: 
     1488                        for value in prop: 
     1489                            styles[prop.name] = (count, prop.name, value.value) 
     1490                            count += 1 
     1491                    style = " ".join("%s: %s;" % (name, value) for (count, name, value) in sorted(styles.itervalues())) 
     1492                    path[-1].attrs.style = style 
     1493        del path[-1][_isstyle] # drop style sheet nodes 
    14481494 
    14491495