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

# Source Code for Module cssutils.css.csspagerule

      1  """CSSPageRule implements DOM Level 2 CSS CSSPageRule.
      2  """
      3  __all__ = ['CSSPageRule']
      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 cssstyledeclaration
     12  import cssutils
     13  from selector import Selector
     14
     15 -class CSSPageRule(cssrule.CSSRule):
     16      """
     17      The CSSPageRule interface represents a @page rule within a CSS style
     18      sheet. The @page rule is used to specify the dimensions, orientation,
     19      margins, etc. of a page box for paged media.
     20
     21      Properties
     22      ==========
     23      cssText: of type DOMString
     24          The parsable textual representation of this rule
     25      selectorText: of type DOMString
     26          The parsable textual representation of the page selector for the rule.
     27      style: of type CSSStyleDeclaration
     28          The declaration-block of this rule.
     29
     30      cssutils only
     31      -------------
     32      atkeyword:
     33          the literal keyword used
     34
     35      Inherits properties from CSSRule
     36
     37      Format
     38      ======
     39      ::
     40
     41          page
     42            : PAGE_SYM S* pseudo_page? S*
     43              LBRACE S* declaration [ ';' S* declaration ]* '}' S*
     44            ;
     45          pseudo_page
     46            : ':' IDENT # :first, :left, :right in CSS 2.1
     47            ;
     48
     49      """
     50      type = cssrule.CSSRule.PAGE_RULE
     51
     52 -    def __init__(self, selectorText=None, style=None, readonly=False):
     53          """
     54          if readonly allows setting of properties in constructor only
     55
     56          selectorText
     57              type string
     58          style
     59              CSSStyleDeclaration for this CSSStyleRule
     60          """
     61          super(CSSPageRule, self).__init__()
     62
     63          self.atkeyword = u'@page'
     64          if selectorText:
     65              self.selectorText = selectorText
     66              self.seq.append(self.selectorText)
     67          else:
     68              self._selectorText = u''
     69          if style:
     70              self.style = style
     71          else:
     72              self._style = cssstyledeclaration.CSSStyleDeclaration(
     73                  parentRule=self)
     74
     75          self._readonly = readonly
     76
     77 -    def __parseSelectorText(self, selectorText):
     78          """
     79          parses selectorText which may also be a list of tokens
     80          and returns (selectorText, seq)
     81
     82          raises SYNTAX_ERR:
     83          """
     84          tokens = self._tokenize(selectorText)
     85
     86          newselectortext = None
     87          newseq = []
     88
     89          expected = ':' # means no selector but 1 like ":first" is okay
     90          i, imax = 0, len(tokens)
     91          while i < imax:
     92              t = tokens[i]
     93              if self._ttypes.S == t.type and 'ident' != expected: # ignore
     94                  pass
     95
     96              elif self._ttypes.COMMENT == t.type and 'ident' != expected: # just add
     97                  newseq.append(cssutils.css.CSSComment(t))
     98
     99              elif u':' == t.value  and ':' == expected: # selector start :
    100                  expected = 'ident'
    101
    102              elif self._ttypes.IDENT == t.type and 'ident' == expected: # selector
    103                  newselectortext = u':%s' % t.value
    104                  newseq.append(newselectortext)
    105                  expected = None
    106
    107              else:
    108                  self._log.error(u'CSSPageRule: Syntax Error in selector: "%s".' %
    109                            self._valuestr(tokens))
    110                  return None, None
    111
    112              i += 1
    113
    114          if expected and expected != ':':
    115              self._log.error(u'CSSPageRule: Invalid Selector: "%s".' %
    116                        self._valuestr(tokens))
    117              return None, None
    118
    119          if newselectortext is None:
    120              newselectortext = u''
    121
    122          # warn only
    123          if not newselectortext in (u'', u':first', u':left', u':right'):
    124              self._log.warn(u'CSSPageRule: Unknown CSS 2.1 @page selector: "%s".' %
    125                       self._valuestr(tokens), neverraise=True)
    126
    127          return newselectortext, newseq
    128
    129 -    def _getCssText(self):
    130          """
    131          returns serialized property cssText
    132          """
    133          return cssutils.ser.do_CSSPageRule(self)
    134
    135 -    def _setCssText(self, cssText):
    136          """
    137          DOMException on setting
    138
    139          - SYNTAX_ERR: (self, StyleDeclaration)
    140            Raised if the specified CSS string value has a syntax error and
    141            is unparsable.
    142          - INVALID_MODIFICATION_ERR: (self)
    143            Raised if the specified CSS string value represents a different
    144            type of rule than the current one.
    145          - HIERARCHY_REQUEST_ERR: (CSSStylesheet)
    146            Raised if the rule cannot be inserted at this point in the
    147            style sheet.
    148          - NO_MODIFICATION_ALLOWED_ERR: (CSSRule)
    149            Raised if the rule is readonly.
    150          """
    151          super(CSSPageRule, self)._setCssText(cssText)
    152          tokens = self._tokenize(cssText)
    153
    154          # check if right token
    155          if not tokens or tokens and tokens[0].type != self._ttypes.PAGE_SYM:
    156              self._log.error(u'CSSPageRule: No CSSPageRule found: %s' %
    157                        self._valuestr(cssText),
    158                        error=xml.dom.InvalidModificationErr)
    159              return
    160          else:
    161              newatkeyword = tokens[0].value
    162
    163          # init
    164          newstyle = cssstyledeclaration.CSSStyleDeclaration(parentRule=self)
    165
    166          # selector
    167          selectortokens, stylestarti = self._tokensupto(
    168              tokens, blockstartonly=True)
    169          newselectortext, newseq = self.__parseSelectorText(
    170              selectortokens[1:-1]) # without @page and {
    171
    172          # style
    173          styletokens, styleendi = self._tokensupto(
    174              tokens[stylestarti:], blockendonly=True)
    175
    176          if not styletokens or \
    177             styletokens[0].value != u'{' or\
    178                 styletokens[-1].type not in(
    179                     self._ttypes.EOF, self._ttypes.RBRACE) or\
    180                 len(tokens) > stylestarti + styleendi + 1:
    181              self._log.error(u'CSSPageRule: Invalid style found: %s' %
    182                        self._valuestr(styletokens[1:-1]))
    183              return
    184
    185          newstyle = cssstyledeclaration.CSSStyleDeclaration(
    186                  parentRule=self, cssText=styletokens[1:-1])
    187
    188          # seems ok
    189          if newstyle:
    190              if newselectortext: # optional
    191                  self._selectorText = newselectortext
    192              self.seq = newseq
    193              self.style = newstyle
    194
    195      cssText = property(_getCssText, _setCssText,
    196          doc="(DOM) The parsable textual representation of the rule.")
    197
    198 -    def _getSelectorText(self):
    199          """
    200          wrapper for cssutils Selector object
    201          """
    202          return self._selectorText
    203
    204 -    def _setSelectorText(self, selectorText):
    205          """
    206          wrapper for cssutils Selector object
    207
    208          selector: DOM String
    209              in CSS 2.1 one of
    210              - :first
    211              - :left
    212              - :right
    213              - empty
    214
    215          If WS or Comments are included they are ignored here! Only
    216          way to add a comment is via setting ``cssText``
    217
    218          DOMException on setting
    219
    220          - SYNTAX_ERR:
    221            Raised if the specified CSS string value has a syntax error
    222            and is unparsable.
    223          - NO_MODIFICATION_ALLOWED_ERR: (self)
    224            Raised if this rule is readonly.
    225          """
    226          self._checkReadonly()
    227
    228          # may raise SYNTAX_ERR
    229          newselectortext, newseq = self.__parseSelectorText(selectorText)
    230
    231          if newselectortext:
    232              for i, x in enumerate(self.seq):
    233                  if x == self._selectorText:
    234                      self.seq[i] = newselectortext
    235              self._selectorText = newselectortext
    236
    237      selectorText = property(_getSelectorText, _setSelectorText,
    238          doc="""(DOM) The parsable textual representation of the page selector for the rule.""")
    239
    240 -    def _getStyle(self):
    241          return self._style
    242
    243 -    def _setStyle(self, style):
    244          """
    245          style
    246              StyleDeclaration or string
    247          """
    248          self._checkReadonly()
    249          if isinstance(style, basestring):
    250              # may raise Exception!
    251              temp = cssstyledeclaration.CSSStyleDeclaration(parentRule=self)
    252              temp.cssText = style
    253              self._style = temp
    254          else:
    255              self._style = style
    256              style.parentRule = self
    257
    258      style = property(_getStyle, _setStyle,
    259          doc="(DOM) The declaration-block of this rule set.")
    260
    261 -    def __repr__(self):
    262          return "cssutils.css.%s(selectorText=%r)" % (
    263                  self.__class__.__name__, self.selectorText)
    264
    265 -    def __str__(self):
    266          return "<cssutils.css.%s object selectorText=%r at 0x%x>" % (
    267                  self.__class__.__name__, self.selectorText, id(self))
    268
    269
    270  if __name__ == '__main__':
    271      import property
    272      cssutils.css.cssstyledeclaration.Property = property._Property
    273      cssutils.css.cssstylerule.Selector = Selector # for main test
    274      r = CSSPageRule()
    275      r.cssText = '@page :right { margin: 0 }'
    276      #r.selectorText = u':left :a'
    277      print r.cssText
    278