Changeset 2821:d149d59fdf49 in livinglogic.python.xist

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

Add an iterator class for recursive iterating all CSS rules in an HTML tree.

html.itercssrules() can be iterated and will collect all <style type="text/css">
and <link rel="stylesheet"> element, parse the CSS files (and any that are
imported via @import) and will produce all rules (this uses the cssutils
package).

Files:
1 modified

Legend:

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

    r2802 r2821  
    99 
    1010 
     11from __future__ import with_statement 
     12 
    1113""" 
    1214<par>An &xist; namespace that contains definitions for all the elements 
     
    1719# $Source$ 
    1820 
    19 import os, cgi 
    20  
    21 from ll.xist import xsc, utils, sims 
     21 
     22import os, cgi, contextlib 
     23 
     24from ll import url 
     25from ll.xist import xsc, utils, sims, xfind 
    2226from ll.xist.ns import xml 
    2327 
     28 
     29object_ = object 
    2430 
    2531xmlns = "http://www.w3.org/1999/xhtml" 
     
    13661372    text = "\n".join(line.rstrip() for line in text.splitlines()) 
    13671373    return text 
     1374 
     1375 
     1376try: 
     1377    import cssutils 
     1378    from cssutils import css, stylesheets 
     1379    from cssutils.css import cssstyledeclaration, cssvalue 
     1380except ImportError: 
     1381    pass 
     1382 
     1383 
     1384class itercssrules(object_): 
     1385    def __init__(self, node, base=None): 
     1386        self.node = node 
     1387        if base is not None: 
     1388            base = url.URL(base) 
     1389        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 
     1396 
     1397    def _fixurl(self, rule, base): 
     1398        for proplist in rule.style.seq: 
     1399            for prop in proplist: 
     1400                for (i, value) in enumerate(prop.cssValue.seq): 
     1401                        if value.startswith("url(") and value.endswith(")"): 
     1402                            if base is not None: 
     1403                                value = "url(%s)" % (base/value[4:-1]) 
     1404                            prop.cssValue.seq[i] = value 
     1405 
     1406    def _doimport(self, parentsheet, base): 
     1407        for rule in parentsheet.cssRules: 
     1408            if rule.type == css.CSSRule.IMPORT_RULE: 
     1409                href = url.URL(rule.href) 
     1410                if base is not None: 
     1411                    href = base/href 
     1412                media = rule.media 
     1413                with contextlib.closing(href.open("rb")) as r: 
     1414                    href = r.finalurl() 
     1415                    text = r.read() 
     1416                sheet = css.CSSStyleSheet(href=str(href), media=media, parentStyleSheet=parentsheet) 
     1417                sheet.cssText = text 
     1418                for rule in self._doimport(sheet, href): 
     1419                    yield rule 
     1420            elif rule.type == css.CSSRule.STYLE_RULE: 
     1421                self._fixurl(rule, base) 
     1422                yield rule 
     1423 
     1424    def __iter__(self): 
     1425        import cssutils 
     1426        for cssnode in self.node.walknode(self._isstyle): 
     1427            if isinstance(cssnode, style): 
     1428                stylesheet = cssutils.parseString(unicode(cssnode.content)) 
     1429                if self.base is not None: 
     1430                    stylesheet.href = str(self.base) 
     1431                for rule in self._doimport(stylesheet, self.base): 
     1432                    yield rule 
     1433            else: # link 
     1434                if "href" in cssnode.attrs: 
     1435                    href = cssnode.attrs.href.asURL() 
     1436                    if self.base is not None: 
     1437                        href = self.base/href 
     1438                    with contextlib.closing(href.open("rb")) as r: 
     1439                        s = r.read() 
     1440                    stylesheet = cssutils.parseString(unicode(s)) 
     1441                    stylesheet.href = str(href) 
     1442                    for rule in self._doimport(stylesheet, href): 
     1443                        yield rule 
    13681444 
    13691445