Package cssutils |
[hide private]
[frames] | no frames]

# Source Code for Package cssutils

      1  #!/usr/bin/env python
      2  """cssutils - CSS Cascading Style Sheets library for Python
      3
      4      Copyright (C) 2004-2008 Christof Hoeke
      5
      6      cssutils is free software: you can redistribute it and/or modify
      7      it under the terms of the GNU Lesser General Public License as published by
      8      the Free Software Foundation, either version 3 of the License, or
      9      (at your option) any later version.
     10
     11      This program is distributed in the hope that it will be useful,
     12      but WITHOUT ANY WARRANTY; without even the implied warranty of
     13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14      GNU Lesser General Public License for more details.
     15
     16      You should have received a copy of the GNU Lesser General Public License
     17      along with this program.  If not, see <http://www.gnu.org/licenses/>.
     18
     19
     20  A Python package to parse and build CSS Cascading Style Sheets. DOM only, not any rendering facilities!
     21
     22  Based upon and partly implementing the following specifications :
     23
     24  `CSS 2.1 <http://www.w3.org/TR/CSS21/>`__
     25      General CSS rules and properties are defined here
     26  `CSS 2.1 Errata  <http://www.w3.org/Style/css2-updates/CR-CSS21-20070719-errata.html>`__
     27      A few errata, mainly the definition of CHARSET_SYM tokens
     28  `CSS3 Module: Syntax <http://www.w3.org/TR/css3-syntax/>`__
     29      Used in parts since cssutils 0.9.4. cssutils tries to use the features from CSS 2.1 and CSS 3 with preference to CSS3 but as this is not final yet some parts are from CSS 2.1
     30  `MediaQueries <http://www.w3.org/TR/css3-mediaqueries/>`__
     31      MediaQueries are part of ``stylesheets.MediaList`` since v0.9.4, used in @import and @media rules.
     32  `Namespaces <http://dev.w3.org/csswg/css3-namespace/>`__
     33      Added in v0.9.1, updated to definition in CSSOM in v0.9.4, updated in 0.9.5 for dev version
     34  `Selectors <http://www.w3.org/TR/css3-selectors/>`__
     35      The selector syntax defined here (and not in CSS 2.1) should be parsable with cssutils (*should* mind though ;) )
     36
     37  `DOM Level 2 Style CSS <http://www.w3.org/TR/DOM-Level-2-Style/css.html>`__
     38      DOM for package css
     39  `DOM Level 2 Style Stylesheets <http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html>`__
     40      DOM for package stylesheets
     41  `CSSOM <http://dev.w3.org/csswg/cssom/>`__
     42      A few details (mainly the NamespaceRule DOM) is taken from here. Plan is to move implementation to the stuff defined here which is newer but still no REC so might change anytime...
     43
     44
     45  The cssutils tokenizer is a customized implementation of `CSS3 Module: Syntax (W3C Working Draft 13 August 2003) <http://www.w3.org/TR/css3-syntax/>`__ which itself is based on the CSS 2.1 tokenizer. It tries to be as compliant as possible but uses some (helpful) parts of the CSS 2.1 tokenizer.
     46
     47  I guess cssutils is neither CSS 2.1 nor CSS 3 compliant but tries to at least be able to parse both grammars including some more real world cases (some CSS hacks are actually parsed and serialized). Both official grammars are not final nor bugfree but still feasible. cssutils aim is not to be fully compliant to any CSS specification (the specifications seem to be in a constant flow anyway) but cssutils *should* be able to read and write as many as possible CSS stylesheets "in the wild" while at the same time implement the official APIs which are well documented. Some minor extensions are provided as well.
     48
     49  Please visit http://cthedot.de/cssutils/ for more details.
     50
     51
     52  Tested with Python 2.5 on Windows Vista mainly.
     53
     54
     55  This library may be used ``from cssutils import *`` which
     56  import subpackages ``css`` and ``stylesheets``, CSSParser and
     57  CSSSerializer classes only.
     58
     59  Usage may be::
     60
     61      >>> from cssutils import *
     62      >>> parser = CSSParser()
     63      >>> sheet = parser.parseString(u'a { color: red}')
     64      >>> print sheet.cssText
     65      a {
     66      color: red
     67      }
     68
     69  """
     70  __all__ = ['css', 'stylesheets', 'CSSParser', 'CSSSerializer']
     71  __docformat__ = 'restructuredtext'
     72  __author__ = 'Christof Hoeke with contributions by Walter Doerwald'
     73  __date__ = '$LastChangedDate:: 2008-07-30 00:42:29 +0200 #$:'
     74  __version__ = '0.9.5 $Id: __init__.py 1406 2008-07-29 22:42:29Z cthedot $'
     75
     76  import codec
     77  import xml.dom
     78
     79  # order of imports is important (maybe as it is partly circular)
     80  from helper import Deprecated
     81  import errorhandler
     82  log = errorhandler.ErrorHandler()
     83
     84  import util
     85  import css
     86  import stylesheets
     87  from parse import CSSParser
     88
     89  from serialize import CSSSerializer
     90  ser = CSSSerializer()
     91
     92  # used by Selector defining namespace prefix '*'
     93  _ANYNS = -1
     94
     95 -class DOMImplementationCSS(object):
     96      """
     97      This interface allows the DOM user to create a CSSStyleSheet
     98      outside the context of a document. There is no way to associate
     99      the new CSSStyleSheet with a document in DOM Level 2.
    100
    101      This class is its *own factory*, as it is given to
    102      xml.dom.registerDOMImplementation which simply calls it and receives
    103      an instance of this class then.
    104      """
    105      _features = [
    106          ('css', '1.0'),
    107          ('css', '2.0'),
    108          ('stylesheets', '1.0'),
    109          ('stylesheets', '2.0')
    110      ]
    111
    112 -    def createCSSStyleSheet(self, title, media):
    113          """
    114          Creates a new CSSStyleSheet.
    115
    116          title of type DOMString
    117              The advisory title. See also the Style Sheet Interfaces
    118              section.
    119          media of type DOMString
    120              The comma-separated list of media associated with the new style
    121              sheet. See also the Style Sheet Interfaces section.
    122
    123          returns
    124              CSSStyleSheet: A new CSS style sheet.
    125
    126          TODO: DOMException
    127              SYNTAX_ERR: Raised if the specified media string value has a
    128              syntax error and is unparsable.
    129          """
    130          return css.CSSStyleSheet(title=title, media=media)
    131
    132 -    def createDocument(self, *args):
    133          # not needed to HTML, also not for CSS?
    134          raise NotImplementedError
    135
    136 -    def createDocumentType(self, *args):
    137          # not needed to HTML, also not for CSS?
    138          raise NotImplementedError
    139
    140 -    def hasFeature(self, feature, version):
    141          return (feature.lower(), unicode(version)) in self._features
    142
    143  xml.dom.registerDOMImplementation('cssutils', DOMImplementationCSS)
    144
    145
    146 -def parseString(*a, **k):
    147      return CSSParser().parseString(*a, **k)
    148  parseString.__doc__ = CSSParser.parseString.__doc__
    149
    150 -def parseFile(*a, **k):
    151      return CSSParser().parseFile(*a, **k)
    152  parseFile.__doc__ = CSSParser.parseFile.__doc__
    153
    154 -def parseUrl(*a, **k):
    155      return CSSParser().parseUrl(*a, **k)
    156  parseUrl.__doc__ = CSSParser.parseUrl.__doc__
    157
    158  @Deprecated('Use cssutils.parseFile() instead.')
    159 -def parse(*a, **k):
    160      return parseFile(*a, **k)
    161  parse.__doc__ = CSSParser.parse.__doc__
    162
    163
    164  # set "ser", default serializer
    165 -def setSerializer(serializer):
    166      """
    167      sets the global serializer used by all class in cssutils
    168      """
    169      global ser
    170      ser = serializer
    171
    172
    173 -def getUrls(sheet):
    174      """
    175      Utility function to get all ``url(urlstring)`` values in
    176      ``CSSImportRules`` and ``CSSStyleDeclaration`` objects (properties)
    177      of given CSSStyleSheet ``sheet``.
    178
    179      This function is a generator. The url values exclude ``url(`` and ``)``
    180      and surrounding single or double quotes.
    181      """
    182      for importrule in (r for r in sheet if r.type == r.IMPORT_RULE):
    183          yield importrule.href
    184
    185      def getUrl(v):
    186          if v.CSS_PRIMITIVE_VALUE == v.cssValueType and\
    187             v.CSS_URI == v.primitiveType:
    188                  return v.getStringValue()
    189
    190      def styleDeclarations(base):
    191          "recursive generator to find all CSSStyleDeclarations"
    192          if hasattr(base, 'cssRules'):
    193              for rule in base.cssRules:
    194                  for s in styleDeclarations(rule):
    195                      yield s
    196          elif hasattr(base, 'style'):
    197              yield base.style
    198
    199      for style in styleDeclarations(sheet):
    200          for p in style.getProperties(all=True):
    201              v = p.cssValue
    202              if v.CSS_VALUE_LIST == v.cssValueType:
    203                  for item in v:
    204                      u = getUrl(item)
    205                      if u is not None:
    206                          yield u
    207              elif v.CSS_PRIMITIVE_VALUE == v.cssValueType:
    208                  u = getUrl(v)
    209                  if u is not None:
    210                      yield u
    211
    212 -def replaceUrls(sheet, replacer):
    213      """
    214      Utility function to replace all ``url(urlstring)`` values in
    215      ``CSSImportRules`` and ``CSSStyleDeclaration`` objects (properties)
    216      of given CSSStyleSheet ``sheet``.
    217
    218      ``replacer`` must be a function which is called with a single
    219      argument ``urlstring`` which is the current value of url()
    220      excluding ``url(`` and ``)`` and surrounding single or double quotes.
    221      """
    222      for importrule in (r for r in sheet if r.type == r.IMPORT_RULE):
    223          importrule.href = replacer(importrule.href)
    224
    225      def setProperty(v):
    226          if v.CSS_PRIMITIVE_VALUE == v.cssValueType and\
    227             v.CSS_URI == v.primitiveType:
    228                  v.setStringValue(v.CSS_URI,
    229                                   replacer(v.getStringValue()))
    230
    231      def styleDeclarations(base):
    232          "recursive generator to find all CSSStyleDeclarations"
    233          if hasattr(base, 'cssRules'):
    234              for rule in base.cssRules:
    235                  for s in styleDeclarations(rule):
    236                      yield s
    237          elif hasattr(base, 'style'):
    238              yield base.style
    239
    240      for style in styleDeclarations(sheet):
    241          for p in style.getProperties(all=True):
    242              v = p.cssValue
    243              if v.CSS_VALUE_LIST == v.cssValueType:
    244                  for item in v:
    245                      setProperty(item)
    246              elif v.CSS_PRIMITIVE_VALUE == v.cssValueType:
    247                  setProperty(v)
    248
    249
    250  if __name__ == '__main__':
    251      print __doc__
    252