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
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
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
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
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
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