Used to insert a new rule into the style sheet. The new rule now becomes part of the cascade. :param rule: a parsable DOMString, in cssutils also a :class:`~cssutils.css.CSSRule` or :class:`~cssutils.css.CSSRuleList` :param index: of the rule before the new rule will be inserted. If the specified `index` is equal to the length of the StyleSheet's rule collection, the rule will be added to the end of the style sheet. If `index` is not given or ``None`` rule will be appended to rule list. :param inOrder: if ``True`` the rule will be put to a proper location while ignoring `index` and without raising :exc:`~xml.dom.HierarchyRequestErr`. The resulting index is returned nevertheless. :returns: The index within the style sheet's rule collection :Exceptions: - :exc:`~xml.dom.HierarchyRequestErr`: Raised if the rule cannot be inserted at the specified `index` e.g. if an @import rule is inserted after a standard rule set or other at-rule. - :exc:`~xml.dom.IndexSizeErr`: Raised if the specified `index` is not a valid insertion point. - :exc:`~xml.dom.NoModificationAllowedErr`: Raised if this style sheet is readonly. - :exc:`~xml.dom.SyntaxErr`: Raised if the specified rule has a syntax error and is unparsable. Definition at line 404 of file cssstylesheet.py. 00404 : """ Used to insert a new rule into the style sheet. The new rule now becomes part of the cascade. :param rule: a parsable DOMString, in cssutils also a :class:`~cssutils.css.CSSRule` or :class:`~cssutils.css.CSSRuleList` :param index: of the rule before the new rule will be inserted. If the specified `index` is equal to the length of the StyleSheet's rule collection, the rule will be added to the end of the style sheet. If `index` is not given or ``None`` rule will be appended to rule list. :param inOrder: if ``True`` the rule will be put to a proper location while ignoring `index` and without raising :exc:`~xml.dom.HierarchyRequestErr`. The resulting index is returned nevertheless. :returns: The index within the style sheet's rule collection :Exceptions: - :exc:`~xml.dom.HierarchyRequestErr`: Raised if the rule cannot be inserted at the specified `index` e.g. if an @import rule is inserted after a standard rule set or other at-rule. - :exc:`~xml.dom.IndexSizeErr`: Raised if the specified `index` is not a valid insertion point. - :exc:`~xml.dom.NoModificationAllowedErr`: Raised if this style sheet is readonly. - :exc:`~xml.dom.SyntaxErr`: Raised if the specified rule has a syntax error and is unparsable. """ self._checkReadonly() # check position if index is None: index = len(self._cssRules) elif index < 0 or index > self._cssRules.length: raise xml.dom.IndexSizeErr( u'CSSStyleSheet: Invalid index %s for CSSRuleList with a length of %s.' % ( index, self._cssRules.length)) return if isinstance(rule, basestring): # init a temp sheet which has the same properties as self tempsheet = CSSStyleSheet(href=self.href, media=self.media, title=self.title, parentStyleSheet=self.parentStyleSheet, ownerRule=self.ownerRule) tempsheet._ownerNode = self.ownerNode tempsheet._fetcher = self._fetcher # prepend encoding if in this sheet to be able to use it in # @import rules encoding resolution # do not add if new rule startswith "@charset" (which is exact!) if not rule.startswith(u'@charset') and (self._cssRules and self._cssRules[0].type == self._cssRules[0].CHARSET_RULE): # rule 0 is @charset! newrulescount, newruleindex = 2, 1 rule = self._cssRules[0].cssText + rule else: newrulescount, newruleindex = 1, 0 # parse the new rule(s) tempsheet.cssText = (rule, self._namespaces) if len(tempsheet.cssRules) != newrulescount or (not isinstance( tempsheet.cssRules[newruleindex], cssutils.css.CSSRule)): self._log.error(u'CSSStyleSheet: Not a CSSRule: %s' % rule) return rule = tempsheet.cssRules[newruleindex] rule._parentStyleSheet = None # done later? # TODO: #tempsheet._namespaces = self._namespaces elif isinstance(rule, cssutils.css.CSSRuleList): # insert all rules for i, r in enumerate(rule): self.insertRule(r, index + i) return index if not rule.wellformed: self._log.error(u'CSSStyleSheet: Invalid rules cannot be added.') return # CHECK HIERARCHY # @charset if rule.type == rule.CHARSET_RULE: if inOrder: index = 0 # always first and only if (self._cssRules and self._cssRules[0].type == rule.CHARSET_RULE): self._cssRules[0].encoding = rule.encoding else: self._cssRules.insert(0, rule) elif index != 0 or (self._cssRules and self._cssRules[0].type == rule.CHARSET_RULE): self._log.error( u'CSSStylesheet: @charset only allowed once at the beginning of a stylesheet.', error=xml.dom.HierarchyRequestErr) return else: self._cssRules.insert(index, rule) # @unknown or comment elif rule.type in (rule.UNKNOWN_RULE, rule.COMMENT) and not inOrder: if index == 0 and self._cssRules and\ self._cssRules[0].type == rule.CHARSET_RULE: self._log.error( u'CSSStylesheet: @charset must be the first rule.', error=xml.dom.HierarchyRequestErr) return else: self._cssRules.insert(index, rule) # @import elif rule.type == rule.IMPORT_RULE: if inOrder: # automatic order if rule.type in (r.type for r in self): # find last of this type for i, r in enumerate(reversed(self._cssRules)): if r.type == rule.type: index = len(self._cssRules) - i break else: # find first point to insert if self._cssRules and self._cssRules[0].type in (rule.CHARSET_RULE, rule.COMMENT): index = 1 else: index = 0 else: # after @charset if index == 0 and self._cssRules and\ self._cssRules[0].type == rule.CHARSET_RULE: self._log.error( u'CSSStylesheet: Found @charset at index 0.', error=xml.dom.HierarchyRequestErr) return # before @namespace, @page, @font-face, @media and stylerule for r in self._cssRules[:index]: if r.type in (r.NAMESPACE_RULE, r.MEDIA_RULE, r.PAGE_RULE, r.STYLE_RULE, r.FONT_FACE_RULE): self._log.error( u'CSSStylesheet: Cannot insert @import here, found @namespace, @media, @page or CSSStyleRule before index %s.' % index, error=xml.dom.HierarchyRequestErr) return self._cssRules.insert(index, rule) # @namespace elif rule.type == rule.NAMESPACE_RULE: if inOrder: if rule.type in (r.type for r in self): # find last of this type for i, r in enumerate(reversed(self._cssRules)): if r.type == rule.type: index = len(self._cssRules) - i break else: # find first point to insert for i, r in enumerate(self._cssRules): if r.type in (r.MEDIA_RULE, r.PAGE_RULE, r.STYLE_RULE, r.FONT_FACE_RULE, r.UNKNOWN_RULE, r.COMMENT): index = i # before these break else: # after @charset and @import for r in self._cssRules[index:]: if r.type in (r.CHARSET_RULE, r.IMPORT_RULE): self._log.error( u'CSSStylesheet: Cannot insert @namespace here, found @charset or @import after index %s.' % index, error=xml.dom.HierarchyRequestErr) return # before @media and stylerule for r in self._cssRules[:index]: if r.type in (r.MEDIA_RULE, r.PAGE_RULE, r.STYLE_RULE, r.FONT_FACE_RULE): self._log.error( u'CSSStylesheet: Cannot insert @namespace here, found @media, @page or CSSStyleRule before index %s.' % index, error=xml.dom.HierarchyRequestErr) return if not (rule.prefix in self.namespaces and self.namespaces[rule.prefix] == rule.namespaceURI): # no doublettes self._cssRules.insert(index, rule) if _clean: self._cleanNamespaces() # all other where order is not important else: if inOrder: # simply add to end as no specific order self._cssRules.append(rule) index = len(self._cssRules) - 1 else: for r in self._cssRules[index:]: if r.type in (r.CHARSET_RULE, r.IMPORT_RULE, r.NAMESPACE_RULE): self._log.error( u'CSSStylesheet: Cannot insert rule here, found @charset, @import or @namespace before index %s.' % index, error=xml.dom.HierarchyRequestErr) return self._cssRules.insert(index, rule) # post settings, TODO: for other rules which contain @rules rule._parentStyleSheet = self if rule.MEDIA_RULE == rule.type: for r in rule: r._parentStyleSheet = self # ? elif rule.IMPORT_RULE == rule.type: rule.href = rule.href # try to reload stylesheet return index ownerRule = property(lambda self: self._ownerRule,
|