def resolveImports(sheet, target=None): """Recurcively combine all rules in given `sheet` into a `target` sheet. @import rules which use media information are tried to be wrapped into @media rules so keeping the media information. This may not work in all instances (if e.g. an @import rule itself contains an @import rule with different media infos or if it is contains rules which may not be used inside an @media block like @namespace rules.). In these cases the @import rule is kept as in the original sheet and a WARNING is issued. :param sheet: in this given :class:`cssutils.css.CSSStyleSheet` all import rules are resolved and added to a resulting *flat* sheet. :param target: A :class:`cssutils.css.CSSStyleSheet` object which will be the resulting *flat* sheet if given :returns: given `target` or a new :class:`cssutils.css.CSSStyleSheet` object """ if not target: target = css.CSSStyleSheet() #target.add(css.CSSComment(cssText=u'/* START %s */' % sheet.href)) for rule in sheet.cssRules: if rule.type == rule.CHARSET_RULE: pass elif rule.type == rule.IMPORT_RULE: log.info(u'Processing @import %r' % rule.href, neverraise=True) if rule.styleSheet: target.add( css.CSSComment(cssText=u'/* START @import "%s" */' % rule.href)) if rule.media.mediaText == 'all': t = target else: log.info(u'Replacing @import media with @media: %s' % rule.media.mediaText, neverraise=True) t = css.CSSMediaRule(rule.media.mediaText) try: resolveImports(rule.styleSheet, t) except xml.dom.HierarchyRequestErr, e: log.warn(u'Cannot resolve @import: %s' % e, neverraise=True) target.add(rule) else: if t != target: target.add(t) t.add(css.CSSComment(cssText=u'/* END "%s" */' % rule.href)) else: log.error(u'Cannot get referenced stylesheet %r' % rule.href, neverraise=True) target.add(rule) else: target.add(rule)
def resolveImports(sheet, target=None): """Recurcively combine all rules in given `sheet` into a `target` sheet. @import rules which use media information are tried to be wrapped into @media rules so keeping the media information. This may not work in all instances (if e.g. an @import rule itself contains an @import rule with different media infos or if it contains rules which may not be used inside an @media block like @namespace rules.). In these cases the @import rule is kept as in the original sheet and a WARNING is issued. :param sheet: in this given :class:`cssutils.css.CSSStyleSheet` all import rules are resolved and added to a resulting *flat* sheet. :param target: A :class:`cssutils.css.CSSStyleSheet` object which will be the resulting *flat* sheet if given :returns: given `target` or a new :class:`cssutils.css.CSSStyleSheet` object """ if not target: target = css.CSSStyleSheet(href=sheet.href, media=sheet.media, title=sheet.title) def getReplacer(targetbase): "Return a replacer which uses base to return adjusted URLs" basesch, baseloc, basepath, basequery, basefrag = urlparse.urlsplit( targetbase) basepath, basepathfilename = os.path.split(basepath) def replacer(uri): scheme, location, path, query, fragment = urlparse.urlsplit(uri) if not scheme and not location and not path.startswith(u'/'): # relative path, filename = os.path.split(path) combined = os.path.normpath( os.path.join(basepath, path, filename)) return urllib.pathname2url(combined) else: # keep anything absolute return uri return replacer for rule in sheet.cssRules: if rule.type == rule.CHARSET_RULE: pass elif rule.type == rule.IMPORT_RULE: log.info(u'Processing @import %r' % rule.href, neverraise=True) if rule.hrefFound: # add all rules of @import to current sheet target.add( css.CSSComment(cssText=u'/* START @import "%s" */' % rule.href)) try: # nested imports importedSheet = resolveImports(rule.styleSheet) except xml.dom.HierarchyRequestErr, e: log.warn( u'@import: Cannot resolve target, keeping rule: %s' % e, neverraise=True) target.add(rule) else: # adjust relative URI references log.info(u'@import: Adjusting paths for %r' % rule.href, neverraise=True) replaceUrls(importedSheet, getReplacer(rule.href), ignoreImportRules=True) # might have to wrap rules in @media if media given if rule.media.mediaText == u'all': mediaproxy = None else: keepimport = False for r in importedSheet: # check if rules present which may not be # combined with media if r.type not in (r.COMMENT, r.STYLE_RULE, r.IMPORT_RULE): keepimport = True break if keepimport: log.warn(u'Cannot combine imported sheet with' u' given media as other rules then' u' comments or stylerules found %r,' u' keeping %r' % (r, rule.cssText), neverraise=True) target.add(rule) continue # wrap in @media if media is not `all` log.info(u'@import: Wrapping some rules in @media ' u' to keep media: %s' % rule.media.mediaText, neverraise=True) mediaproxy = css.CSSMediaRule(rule.media.mediaText) for r in importedSheet: if mediaproxy: mediaproxy.add(r) else: # add to top sheet directly but are difficult anyway target.add(r) if mediaproxy: target.add(mediaproxy) else: # keep @import as it is log.error( u'Cannot get referenced stylesheet %r, keeping rule' % rule.href, neverraise=True) target.add(rule) else: target.add(rule)