Package cssutils :: Package css :: Module cssmediarule |
[hide private]
[frames] | no frames]

# Source Code for Module cssutils.css.cssmediarule

      1  """CSSMediaRule implements DOM Level 2 CSS CSSMediaRule.
      2  """
      3  __all__ = ['CSSMediaRule']
      4  __docformat__ = 'restructuredtext'
      5  __author__ = '$LastChangedBy: cthedot $'
      6  __date__ = '$LastChangedDate: 2007-08-20 22:07:12 +0200 (Mo, 20 Aug 2007) $'
      7  __version__ = '$LastChangedRevision: 257 $'
      8
      9  import xml.dom
     10  import cssrule
     11  import cssutils
     12
     13 -class CSSMediaRule(cssrule.CSSRule):
     14      """
     15      represents an @media rule in a CSS style sheet. A @media rule can be
     16      used to delimit style rules for specific media types.
     17
     18      Properties
     19      ==========
     20      cssRules: A css::CSSRuleList of all CSS rules contained within the
     21          media block.
     22      cssText: of type DOMString
     23          The parsable textual representation of this rule
     24      media: of type stylesheets::MediaList, (DOM readonly)
     25          A list of media types for this rule of type MediaList.
     26
     27      cssutils only
     28      -------------
     29      atkeyword:
     30          the literal keyword used
     31
     32      Inherits properties from CSSRule
     33
     34      Format
     35      ======
     36      media
     37        : MEDIA_SYM S* medium [ COMMA S* medium ]* LBRACE S* ruleset* '}' S*;
     38      """
     39      # CONSTANT
     40      type = cssrule.CSSRule.MEDIA_RULE
     41
     42 -    def __init__(self, mediaText='all', readonly=False):
     43          """
     44          constructor
     45          """
     46          super(CSSMediaRule, self).__init__()
     47
     48          self.atkeyword = u'@media'
     49          self._media = cssutils.stylesheets.MediaList(
     50              mediaText, readonly=readonly)
     51          if not self.media.valid:
     52              self._media = cssutils.stylesheets.MediaList()
     53          self._rules = cssutils.css.cssrulelist.CSSRuleList()
     54
     55          self._readonly = readonly
     56
     57 -    def _getMedia(self):
     58          "returns MediaList"
     59          return self._media
     60
     61      media = property(_getMedia,
     62          doc=u"(DOM readonly) A list of media types for this rule of type\
     63              MediaList")
     64
     65 -    def _getCssRules(self):
     66          return self._rules
     67
     68      cssRules = property(_getCssRules,
     69          doc="(DOM readonly) A css::CSSRuleList of all CSS rules contained\
     70              within the media block.")
     71
     72 -    def deleteRule(self, index):
     73          """
     74          index
     75              within the media block's rule collection of the rule to remove.
     76
     77          Used to delete a rule from the media block.
     78
     79          DOMExceptions
     80
     81          - INDEX_SIZE_ERR: (self)
     82            Raised if the specified index does not correspond to a rule in
     83            the media rule list.
     84          - NO_MODIFICATION_ALLOWED_ERR: (self)
     85            Raised if this media rule is readonly.
     86          """
     87          self._checkReadonly()
     88
     89          try:
     90              self._rules[index].parentRule = None # detach
     91              del self._rules[index] # remove from @media
     92          except IndexError:
     93              raise xml.dom.IndexSizeErr(
     94                  u'CSSMediaRule: %s is not a valid index in the rulelist of length %i' % (
     95                  index, self.cssRules.length))
     96
     97 -    def insertRule(self, rule, index=None):
     98          """
     99          rule
    100              The parsable text representing the rule. For rule sets this
    101              contains both the selector and the style declaration. For
    102              at-rules, this specifies both the at-identifier and the rule
    103              content.
    104
    105              cssutils also allows rule to be a valid **CSSRule** object
    106
    107          index
    108              within the media block's rule collection of the rule before
    109              which to insert the specified rule. If the specified index is
    110              equal to the length of the media blocks's rule collection, the
    111              rule will be added to the end of the media block.
    112              If index is not given or None rule will be appended to rule
    113              list.
    114
    115          Used to insert a new rule into the media block.
    116
    117          DOMException on setting
    118
    119          - HIERARCHY_REQUEST_ERR:
    120            (no use case yet as no @charset or @import allowed))
    121            Raised if the rule cannot be inserted at the specified index,
    122            e.g., if an @import rule is inserted after a standard rule set
    123            or other at-rule.
    124          - INDEX_SIZE_ERR: (self)
    125            Raised if the specified index is not a valid insertion point.
    126          - NO_MODIFICATION_ALLOWED_ERR: (self)
    127            Raised if this media rule is readonly.
    128          - SYNTAX_ERR: (CSSStyleRule)
    129            Raised if the specified rule has a syntax error and is
    130            unparsable.
    131
    132          returns the index within the media block's rule collection of the
    133          newly inserted rule.
    134
    135          """
    136          self._checkReadonly()
    137
    138          # check position
    139          if index is None:
    140              index = len(self.cssRules)
    141          elif index < 0 or index > self.cssRules.length:
    142              raise xml.dom.IndexSizeErr(
    143                  u'CSSMediaRule: Invalid index %s for CSSRuleList with a length of %s.' % (
    144                      index, self.cssRules.length))
    145
    146          # parse
    147          if isinstance(rule, basestring):
    148              tempsheet = CSSStyleSheet()
    149              tempsheet.cssText = rule
    150              if len(tempsheet.cssRules) != 1 or (tempsheet.cssRules and
    151               not isinstance(tempsheet.cssRules[0], cssutils.css.CSSRule)):
    152                  self._log.error(u'CSSMediaRule: Invalid Rule: %s' % rule)
    153                  return
    154              rule = tempsheet.cssRules[0]
    155          elif not isinstance(rule, cssutils.css.CSSRule):
    156              self._log.error(u'CSSMediaRule: Not a CSSRule: %s' % rule)
    157              return
    158
    159          # CHECK HIERARCHY
    160          # @charset @import @media -> TODO: @page @namespace
    161          if isinstance(rule, cssutils.css.CSSCharsetRule) or \
    162             isinstance(rule, cssutils.css.CSSImportRule) or \
    163             isinstance(rule, CSSMediaRule):
    164              self._log.error(u'CSSMediaRule: This type of rule is not allowed here: %s' %
    165                        rule.cssText,
    166                        error=xml.dom.HierarchyRequestErr)
    167              return
    168
    169          self.cssRules.insert(index, rule)
    170          rule.parentRule = self
    171          return index
    172
    173 -    def _getCssText(self):
    174          """
    175          returns serialized property cssText
    176          """
    177          return cssutils.ser.do_CSSMediaRule(self)
    178
    179 -    def _setCssText(self, cssText):
    180          """
    181          DOMException on setting
    182
    183          - NO_MODIFICATION_ALLOWED_ERR: (self)
    184            Raised if the rule is readonly.
    185          - INVALID_MODIFICATION_ERR: (self)
    186            Raised if the specified CSS string value represents a different
    187            type of rule than the current one.
    188          - HIERARCHY_REQUEST_ERR: (self)
    189            Raised if the rule cannot be inserted at this point in the
    190            style sheet.
    191          - SYNTAX_ERR: (self)
    192            Raised if the specified CSS string value has a syntax error and
    193            is unparsable.
    194          """
    195          super(CSSMediaRule, self)._setCssText(cssText)
    196          tokens = self._tokenize(cssText)
    197          valid = True
    198
    199          # check if right token
    200          if not tokens or tokens and tokens[0].type != self._ttypes.MEDIA_SYM:
    201              self._log.error(u'CSSMediaRule: No CSSMediaRule found: %s' %
    202                        self._valuestr(cssText),
    203                        error=xml.dom.InvalidModificationErr)
    204              return
    205          else:
    206              newatkeyword = tokens[0].value
    207
    208          newmedia = cssutils.stylesheets.MediaList()
    209          mediatokens, endi = self._tokensupto(tokens[1:],
    210                                                      blockstartonly=True)
    211
    212          # checks if media ends with rules start and if at least
    213          # one media found, medialist default to all which is wrong here!
    214          if mediatokens and mediatokens[-1].value == u'{' and \
    215             self._ttypes.IDENT in [_t.type for _t in mediatokens]:
    216              newmedia.mediaText = mediatokens[:-1]
    217          else:
    218              self._log.error(xml.dom.SyntaxErr(
    219                  u'CSSMediaRule: Syntax error in MediaList: %s' %
    220                  self._valuestr(cssText)))
    221              return
    222
    223          newrules = cssutils.css.CSSRuleList()
    224          i, imax = endi + 2, len(tokens)
    225          while i < imax:
    226              t = tokens[i]
    227
    228              if t.type == self._ttypes.EOF:
    229                  break
    230
    231              elif self._ttypes.S == t.type: # ignore
    232                  pass
    233
    234              elif self._ttypes.COMMENT == t.type: # just add
    235                  newrules.append(cssutils.css.CSSComment(t))
    236
    237              elif u'}' == t.value: # end
    238                  if i+1 < len(tokens):
    239                      self._log.error(
    240                          u'CSSMediaRule: Unexpected tokens found: "%s".'
    241                          % self._valuestr(tokens[i:]), t)
    242                  break
    243
    244              elif self._ttypes.ATKEYWORD == t.type:
    245                  # @UNKNOWN
    246                  self._log.info(u'CSSMediaRule: Found unknown @rule.', t,
    247                           error=None)
    248                  atruletokens, endi = self._tokensupto(tokens[i:])
    249                  i += endi
    250                  atrule = cssutils.css.CSSUnknownRule()
    251                  atrule.cssText = atruletokens
    252                  newrules.append(atrule)
    253
    254              elif t.type in (self._ttypes.CHARSET_SYM, self._ttypes.IMPORT_SYM,
    255                              self._ttypes.MEDIA_SYM, self._ttypes.PAGE_SYM):
    256                  atruletokens, endi = self._tokensupto(tokens[i:])
    257                  i += endi + 1
    258                  self._log.error(
    259                      u'CSSMediaRule: This rule is not allowed in CSSMediaRule - ignored: %s.'
    260                      % self._valuestr(atruletokens), t,
    261                      xml.dom.HierarchyRequestErr)
    262                  continue
    263
    264              else:
    265                  # StyleRule
    266                  ruletokens, endi = self._tokensupto(
    267                      tokens[i:], blockendonly=True)
    268                  i += endi
    269                  rule = cssutils.css.CSSStyleRule()
    270                  rule.cssText = ruletokens
    271                  newrules.append(rule)
    272
    273              i += 1
    274
    275          if valid:
    276              self.atkeyword = newatkeyword
    277              self._media = newmedia
    278              self._rules = newrules
    279              for r in self._rules:
    280                  r.parentRule = self
    281
    282      cssText = property(_getCssText, _setCssText,
    283          doc="(DOM attribute) The parsable textual representation.")
    284
    285 -    def __repr__(self):
    286          return "cssutils.css.%s(mediaText=%r)" % (
    287                  self.__class__.__name__, self.media.mediaText)
    288
    289 -    def __str__(self):
    290          return "<cssutils.css.%s object mediaText=%r at 0x%x>" % (
    291                  self.__class__.__name__, self.media.mediaText, id(self))
    292
    293
    294  if __name__ == '__main__':
    295      m = CSSMediaRule()
    296      m.cssText = u'@media all {@;}'
    297      print m.cssText
    298