Esempio n. 1
0
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)
Esempio n. 2
0
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)