Beispiel #1
0
 def _getVariables(self):
     "Returns CSSVariablesDeclaration of all variables available."
     vars = CSSVariablesDeclaration()
     
     for r in self.cssRules.rulesOfType(CSSRule.IMPORT_RULE):
         for vr in r.styleSheet.cssRules.rulesOfType(CSSRule.VARIABLES_RULE):
             for var in vr.variables:
                 vars.setVariable(var, vr.variables[var])
     for vr in self.cssRules.rulesOfType(CSSRule.VARIABLES_RULE):
         for var in vr.variables:
             vars.setVariable(var, vr.variables[var])
     
     return vars
Beispiel #2
0
    def __init__(self,
                 href=None,
                 media=None,
                 title=u'',
                 disabled=None,
                 ownerNode=None,
                 parentStyleSheet=None,
                 readonly=False,
                 ownerRule=None):
        """
        For parameters see :class:`~cssutils.stylesheets.StyleSheet`
        """
        super(CSSStyleSheet,
              self).__init__('text/css', href, media, title, disabled,
                             ownerNode, parentStyleSheet)

        self._ownerRule = ownerRule
        self.cssRules = cssutils.css.CSSRuleList()
        self._namespaces = _Namespaces(parentStyleSheet=self, log=self._log)
        self._variables = CSSVariablesDeclaration()
        self._readonly = readonly

        # used only during setting cssText by parse*()
        self.__encodingOverride = None
        self._fetcher = None
Beispiel #3
0
 def _setVariables(self, variables):
     """
     :param variables:
         a CSSVariablesDeclaration or string
     """
     self._checkReadonly()
     if isinstance(variables, basestring):
         self._variables = CSSVariablesDeclaration(cssText=variables,
                                                   parentRule=self)
     else:
         variables._parentRule = self
         self._variables = variables
Beispiel #4
0
    def __init__(self,
                 mediaText=None,
                 variables=None,
                 parentRule=None,
                 parentStyleSheet=None,
                 readonly=False):
        """
        If readonly allows setting of properties in constructor only.
        """
        super(CSSVariablesRule,
              self).__init__(parentRule=parentRule,
                             parentStyleSheet=parentStyleSheet)
        self._atkeyword = u'@variables'

        # dummy
        self._media = cssutils.stylesheets.MediaList(mediaText,
                                                     readonly=readonly)

        if variables:
            self.variables = variables
        else:
            self.variables = CSSVariablesDeclaration(parentRule=self)

        self._readonly = readonly
Beispiel #5
0
    def _setCssText(self, cssText):
        """Parse `cssText` and overwrites the whole stylesheet.

        :param cssText:
            a parseable string or a tuple of (cssText, dict-of-namespaces)
        :exceptions:
            - :exc:`~xml.dom.NamespaceErr`:
              If a namespace prefix is found which is not declared.
            - :exc:`~xml.dom.NoModificationAllowedErr`:
              Raised if the rule is readonly.
            - :exc:`~xml.dom.SyntaxErr`:
              Raised if the specified CSS string value has a syntax error and
              is unparsable.
        """
        self._checkReadonly()

        cssText, namespaces = self._splitNamespacesOff(cssText)
        tokenizer = self._tokenize2(cssText)

        def S(expected, seq, token, tokenizer=None):
            # @charset must be at absolute beginning of style sheet
            return max(1, expected)

        def COMMENT(expected, seq, token, tokenizer=None):
            "special: sets parent*"
            self.insertRule(
                cssutils.css.CSSComment([token], parentStyleSheet=self))
            return max(1, expected)

        def charsetrule(expected, seq, token, tokenizer):
            # parse and consume tokens in any case
            rule = cssutils.css.CSSCharsetRule(parentStyleSheet=self)
            rule.cssText = self._tokensupto2(tokenizer, token)

            if expected > 0:
                self._log.error(
                    u'CSSStylesheet: CSSCharsetRule only allowed '
                    u'at beginning of stylesheet.', token,
                    xml.dom.HierarchyRequestErr)
                return expected
            elif rule.wellformed:
                self.insertRule(rule)

            return 1

        def importrule(expected, seq, token, tokenizer):
            # parse and consume tokens in any case
            rule = cssutils.css.CSSImportRule(parentStyleSheet=self)
            rule.cssText = self._tokensupto2(tokenizer, token)

            if expected > 1:
                self._log.error(
                    u'CSSStylesheet: CSSImportRule not allowed '
                    u'here.', token, xml.dom.HierarchyRequestErr)
                return expected
            elif rule.wellformed:
                self.insertRule(rule)

            return 1

        def namespacerule(expected, seq, token, tokenizer):
            # parse and consume tokens in any case
            rule = cssutils.css.CSSNamespaceRule(cssText=self._tokensupto2(
                tokenizer, token),
                                                 parentStyleSheet=self)

            if expected > 2:
                self._log.error(
                    u'CSSStylesheet: CSSNamespaceRule not allowed '
                    u'here.', token, xml.dom.HierarchyRequestErr)
                return expected
            elif rule.wellformed:
                if rule.prefix not in self.namespaces:
                    # add new if not same prefix
                    self.insertRule(rule, _clean=False)
                else:
                    # same prefix => replace namespaceURI
                    for r in self.cssRules.rulesOfType(rule.NAMESPACE_RULE):
                        if r.prefix == rule.prefix:
                            r._replaceNamespaceURI(rule.namespaceURI)

                self._namespaces[rule.prefix] = rule.namespaceURI

            return 2

        def variablesrule(expected, seq, token, tokenizer):
            # parse and consume tokens in any case
            rule = cssutils.css.CSSVariablesRule(parentStyleSheet=self)
            rule.cssText = self._tokensupto2(tokenizer, token)

            if expected > 2:
                self._log.error(
                    u'CSSStylesheet: CSSVariablesRule not allowed '
                    u'here.', token, xml.dom.HierarchyRequestErr)
                return expected
            elif rule.wellformed:
                self.insertRule(rule)
                self._updateVariables()

            return 2

        def fontfacerule(expected, seq, token, tokenizer):
            # parse and consume tokens in any case
            rule = cssutils.css.CSSFontFaceRule(parentStyleSheet=self)
            rule.cssText = self._tokensupto2(tokenizer, token)
            if rule.wellformed:
                self.insertRule(rule)
            return 3

        def mediarule(expected, seq, token, tokenizer):
            # parse and consume tokens in any case
            rule = cssutils.css.CSSMediaRule(parentStyleSheet=self)
            rule.cssText = self._tokensupto2(tokenizer, token)
            if rule.wellformed:
                self.insertRule(rule)
            return 3

        def pagerule(expected, seq, token, tokenizer):
            # parse and consume tokens in any case
            rule = cssutils.css.CSSPageRule(parentStyleSheet=self)
            rule.cssText = self._tokensupto2(tokenizer, token)
            if rule.wellformed:
                self.insertRule(rule)
            return 3

        def unknownrule(expected, seq, token, tokenizer):
            # parse and consume tokens in any case
            self._log.warn(u'CSSStylesheet: Unknown @rule found.',
                           token,
                           neverraise=True)
            rule = cssutils.css.CSSUnknownRule(self._tokensupto2(
                tokenizer, token),
                                               parentStyleSheet=self)
            if rule.wellformed:
                self.insertRule(rule)

            return max(1, expected)

        def ruleset(expected, seq, token, tokenizer):
            # parse and consume tokens in any case
            rule = cssutils.css.CSSStyleRule(parentStyleSheet=self)
            rule.cssText = self._tokensupto2(tokenizer, token)
            if rule.wellformed:
                self.insertRule(rule)
            return 3

        # save for possible reset
        oldCssRules = self.cssRules
        oldNamespaces = self._namespaces

        self.cssRules = cssutils.css.CSSRuleList()
        # simple during parse
        self._namespaces = namespaces
        self._variables = CSSVariablesDeclaration()

        # not used?!
        newseq = []

        # ['CHARSET', 'IMPORT', ('VAR', NAMESPACE'), ('PAGE', 'MEDIA', ruleset)]
        wellformed, expected = self._parse(0,
                                           newseq,
                                           tokenizer, {
                                               'S': S,
                                               'COMMENT': COMMENT,
                                               'CDO': lambda *ignored: None,
                                               'CDC': lambda *ignored: None,
                                               'CHARSET_SYM': charsetrule,
                                               'FONT_FACE_SYM': fontfacerule,
                                               'IMPORT_SYM': importrule,
                                               'NAMESPACE_SYM': namespacerule,
                                               'PAGE_SYM': pagerule,
                                               'MEDIA_SYM': mediarule,
                                               'VARIABLES_SYM': variablesrule,
                                               'ATKEYWORD': unknownrule
                                           },
                                           default=ruleset)

        if wellformed:
            # use proper namespace object
            self._namespaces = _Namespaces(parentStyleSheet=self,
                                           log=self._log)
            self._cleanNamespaces()

        else:
            # reset
            self._cssRules = oldCssRules
            self._namespaces = oldNamespaces
            self._updateVariables()
            self._cleanNamespaces()
    def _setCssText(self, cssText):
        """
        :exceptions:
            - :exc:`~xml.dom.SyntaxErr`:
              Raised if the specified CSS string value has a syntax error and
              is unparsable.
            - :exc:`~xml.dom.InvalidModificationErr`:
              Raised if the specified CSS string value represents a different
              type of rule than the current one.
            - :exc:`~xml.dom.HierarchyRequestErr`:
              Raised if the rule cannot be inserted at this point in the
              style sheet.
            - :exc:`~xml.dom.NoModificationAllowedErr`:
              Raised if the rule is readonly.
              
        Format::
        
            variables
            : VARIABLES_SYM S* medium [ COMMA S* medium ]* LBRACE S* 
              variableset* '}' S*
            ;
            
            variableset
            : LBRACE S* vardeclaration [ ';' S* vardeclaration ]* '}' S*
            ;
        """
        super(CSSVariablesRule, self)._setCssText(cssText)

        tokenizer = self._tokenize2(cssText)
        attoken = self._nexttoken(tokenizer, None)
        if self._type(attoken) != self._prods.VARIABLES_SYM:
            self._log.error(u'CSSVariablesRule: No CSSVariablesRule found: %s' %
                            self._valuestr(cssText),
                            error=xml.dom.InvalidModificationErr)
        else:
            newVariables = CSSVariablesDeclaration(parentRule=self)
            ok = True
            
            beforetokens, brace = self._tokensupto2(tokenizer, 
                                                    blockstartonly=True,
                                                    separateEnd=True)            
            if self._tokenvalue(brace) != u'{':
                ok = False
                self._log.error(u'CSSVariablesRule: No start { of variable '
                                u'declaration found: %r' 
                                % self._valuestr(cssText), brace)
            
            # parse stuff before { which should be comments and S only
            new = {'wellformed': True}
            newseq = self._tempSeq()#[]
            
            beforewellformed, expected = self._parse(expected=':',
                seq=newseq, tokenizer=self._tokenize2(beforetokens),
                productions={})
            ok = ok and beforewellformed and new['wellformed']
    
            variablestokens, braceorEOFtoken = self._tokensupto2(tokenizer, 
                                                             blockendonly=True,
                                                             separateEnd=True)

            val, type_ = self._tokenvalue(braceorEOFtoken), \
                         self._type(braceorEOFtoken)
            if val != u'}' and type_ != 'EOF':
                ok = False
                self._log.error(u'CSSVariablesRule: No "}" after variables '
                                u'declaration found: %r'
                                % self._valuestr(cssText))
                
            nonetoken = self._nexttoken(tokenizer)
            if nonetoken:
                ok = False
                self._log.error(u'CSSVariablesRule: Trailing content found.',
                                token=nonetoken)

            if 'EOF' == type_:
                # add again as variables needs it
                variablestokens.append(braceorEOFtoken)
            # SET but may raise:
            newVariables.cssText = variablestokens

            if ok:
                # contains probably comments only upto {
                self._setSeq(newseq)
                self.variables = newVariables
Beispiel #7
0
    def _setCssText(self, cssText):
        """
        :exceptions:
            - :exc:`~xml.dom.SyntaxErr`:
              Raised if the specified CSS string value has a syntax error and
              is unparsable.
            - :exc:`~xml.dom.InvalidModificationErr`:
              Raised if the specified CSS string value represents a different
              type of rule than the current one.
            - :exc:`~xml.dom.HierarchyRequestErr`:
              Raised if the rule cannot be inserted at this point in the
              style sheet.
            - :exc:`~xml.dom.NoModificationAllowedErr`:
              Raised if the rule is readonly.
              
        Format::
        
            variables
            : VARIABLES_SYM S* medium [ COMMA S* medium ]* LBRACE S* 
              variableset* '}' S*
            ;
            
            variableset
            : LBRACE S* vardeclaration [ ';' S* vardeclaration ]* '}' S*
            ;
        """
        super(CSSVariablesRule, self)._setCssText(cssText)

        tokenizer = self._tokenize2(cssText)
        attoken = self._nexttoken(tokenizer, None)
        if self._type(attoken) != self._prods.VARIABLES_SYM:
            self._log.error(
                u'CSSVariablesRule: No CSSVariablesRule found: %s' %
                self._valuestr(cssText),
                error=xml.dom.InvalidModificationErr)
        else:
            newVariables = CSSVariablesDeclaration(parentRule=self)
            ok = True

            beforetokens, brace = self._tokensupto2(tokenizer,
                                                    blockstartonly=True,
                                                    separateEnd=True)
            if self._tokenvalue(brace) != u'{':
                ok = False
                self._log.error(
                    u'CSSVariablesRule: No start { of variable '
                    u'declaration found: %r' % self._valuestr(cssText), brace)

            # parse stuff before { which should be comments and S only
            new = {'wellformed': True}
            newseq = self._tempSeq()  #[]

            beforewellformed, expected = self._parse(
                expected=':',
                seq=newseq,
                tokenizer=self._tokenize2(beforetokens),
                productions={})
            ok = ok and beforewellformed and new['wellformed']

            variablestokens, braceorEOFtoken = self._tokensupto2(
                tokenizer, blockendonly=True, separateEnd=True)

            val, type_ = self._tokenvalue(braceorEOFtoken), \
                         self._type(braceorEOFtoken)
            if val != u'}' and type_ != 'EOF':
                ok = False
                self._log.error(u'CSSVariablesRule: No "}" after variables '
                                u'declaration found: %r' %
                                self._valuestr(cssText))

            nonetoken = self._nexttoken(tokenizer)
            if nonetoken:
                ok = False
                self._log.error(u'CSSVariablesRule: Trailing content found.',
                                token=nonetoken)

            if 'EOF' == type_:
                # add again as variables needs it
                variablestokens.append(braceorEOFtoken)
            # SET but may raise:
            newVariables.cssText = variablestokens

            if ok:
                # contains probably comments only upto {
                self._setSeq(newseq)
                self.variables = newVariables