From 33a1617f8997aa129a31234502ea47642fa79e38 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 10 Mar 2012 14:57:42 +0530 Subject: [PATCH] Conversion pipeline: Fix @import rules in CSS stylesheets that have comments on their first few lines being ignored. Also use cssutils to process @import rules instead of doing it ourselves. --- src/calibre/ebooks/conversion/preprocess.py | 9 +++++- src/calibre/ebooks/oeb/base.py | 32 +++------------------ 2 files changed, 12 insertions(+), 29 deletions(-) diff --git a/src/calibre/ebooks/conversion/preprocess.py b/src/calibre/ebooks/conversion/preprocess.py index dc10a60f2f..617de18555 100644 --- a/src/calibre/ebooks/conversion/preprocess.py +++ b/src/calibre/ebooks/conversion/preprocess.py @@ -289,10 +289,17 @@ class CSSPreProcessor(object): data = self.MS_PAT.sub(self.ms_sub, data) if not add_namespace: return data + + # Remove comments as the following namespace logic will break if there + # are commented lines before the first @import or @charset rule. Since + # the conversion will remove all stylesheets anyway, we don't lose + # anything + data = re.sub(ur'/\*.*?\*/', u'', data, flags=re.DOTALL) + ans, namespaced = [], False for line in data.splitlines(): ll = line.lstrip() - if not (namespaced or ll.startswith('@import') or + if not (namespaced or ll.startswith('@import') or not ll or ll.startswith('@charset')): ans.append(XHTML_CSS_NAMESPACE.strip()) namespaced = True diff --git a/src/calibre/ebooks/oeb/base.py b/src/calibre/ebooks/oeb/base.py index a9608105f9..450d50fd40 100644 --- a/src/calibre/ebooks/oeb/base.py +++ b/src/calibre/ebooks/oeb/base.py @@ -832,22 +832,8 @@ class Manifest(object): def _parse_css(self, data): - from cssutils.css import CSSRule - from cssutils import CSSParser, log + from cssutils import CSSParser, log, resolveImports log.setLevel(logging.WARN) - def get_style_rules_from_import(import_rule): - ans = [] - if not import_rule.styleSheet: - return ans - rules = import_rule.styleSheet.cssRules - for rule in rules: - if rule.type == CSSRule.IMPORT_RULE: - ans.extend(get_style_rules_from_import(rule)) - elif rule.type in (CSSRule.FONT_FACE_RULE, - CSSRule.STYLE_RULE): - ans.append(rule) - return ans - self.oeb.log.debug('Parsing', self.href, '...') data = self.oeb.decode(data) data = self.oeb.css_preprocessor(data, add_namespace=True) @@ -855,19 +841,8 @@ class Manifest(object): fetcher=self.override_css_fetch or self._fetch_css, log=_css_logger) data = parser.parseString(data, href=self.href) + data = resolveImports(data) data.namespaces['h'] = XHTML_NS - import_rules = list(data.cssRules.rulesOfType(CSSRule.IMPORT_RULE)) - rules_to_append = [] - insert_index = None - for r in data.cssRules.rulesOfType(CSSRule.STYLE_RULE): - insert_index = data.cssRules.index(r) - break - for rule in import_rules: - rules_to_append.extend(get_style_rules_from_import(rule)) - for r in reversed(rules_to_append): - data.insertRule(r, index=insert_index) - for rule in import_rules: - data.deleteRule(rule) return data def _fetch_css(self, path): @@ -880,7 +855,8 @@ class Manifest(object): self.oeb.logger.warn('CSS import of non-CSS file %r' % path) return (None, None) data = item.data.cssText - return ('utf-8', data) + enc = None if isinstance(data, unicode) else 'utf-8' + return (enc, data) # }}}