From bdd03a58d26098fc0dcbe5a708762d08e20007a7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 27 Nov 2013 15:56:25 +0530 Subject: [PATCH] Expand shorthand properties in filter CSS Conversion: Fix specifying shorthand properties in filter css not working. Now all shorthand properties automatically filter out all the properties they are shorthand for. --- src/calibre/ebooks/oeb/normalize_css.py | 36 +++++++++++++++++++- src/calibre/ebooks/oeb/transforms/flatcss.py | 6 ++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/calibre/ebooks/oeb/normalize_css.py b/src/calibre/ebooks/oeb/normalize_css.py index d1f7eb0783..311bd7ca9b 100644 --- a/src/calibre/ebooks/oeb/normalize_css.py +++ b/src/calibre/ebooks/oeb/normalize_css.py @@ -13,7 +13,7 @@ try: from cssutils.css import PropertyValue except ImportError: raise RuntimeError('You need cssutils >= 0.9.9 for calibre') -from cssutils import profile as cssprofiles +from cssutils import profile as cssprofiles, CSSParser DEFAULTS = {'azimuth': 'center', 'background-attachment': 'scroll', # {{{ 'background-color': 'transparent', 'background-image': 'none', @@ -165,6 +165,25 @@ for x in EDGES: name = 'border-' + x normalizers[name] = simple_normalizer(name, BORDER_PROPS, check_inherit=False) +SHORTHAND_DEFAULTS = { + 'margin': '0', 'padding': '0', 'border-style': 'none', 'border-width': '0', 'border-color': 'currentColor', + 'border':'none', 'border-left': 'none', 'border-right':'none', 'border-top': 'none', 'border-bottom': 'none', + 'list-style': 'inherit', 'font': 'inherit', +} + +def normalize_filter_css(props): + import logging + ans = set() + p = CSSParser(loglevel=logging.CRITICAL, validate=False) + for prop in props: + n = normalizers.get(prop, None) + ans.add(prop) + if n is not None and prop in SHORTHAND_DEFAULTS: + dec = p.parseStyle('%s: %s' % (prop, SHORTHAND_DEFAULTS[prop])) + cssvalue = dec.getPropertyCSSValue(dec.item(0)) + ans |= set(n(prop, cssvalue)) + return ans + def condense_edge(vals): edges = {x.name.rpartition('-')[-1]:x.value for x in vals} if len(edges) != 4: @@ -337,6 +356,21 @@ def test_normalization(): # {{{ cval = tuple(parseStyle('list-style: %s' % raw, validate=False))[0].cssValue self.assertDictEqual(ls_dict(expected), normalizers['list-style']('list-style', cval)) + def test_filter_css_normalization(self): + ae = self.assertEqual + ae({'font'} | set(font_composition), normalize_filter_css({'font'})) + for p in ('margin', 'padding'): + ae({p} | {p + '-' + x for x in EDGES}, normalize_filter_css({p})) + bvals = {'border-%s-%s' % (edge, x) for edge in EDGES for x in BORDER_PROPS} + ae(bvals | {'border'}, normalize_filter_css({'border'})) + for x in BORDER_PROPS: + sbvals = {'border-%s-%s' % (e, x) for e in EDGES} + ae(sbvals | {'border-%s' % x}, normalize_filter_css({'border-%s' % x})) + for e in EDGES: + sbvals = {'border-%s-%s' % (e, x) for x in BORDER_PROPS} + ae(sbvals | {'border-%s' % e}, normalize_filter_css({'border-%s' % e})) + ae({'list-style', 'list-style-image', 'list-style-type', 'list-style-position'}, normalize_filter_css({'list-style'})) + def test_edge_condensation(self): for s, v in { (1, 1, 3) : None, diff --git a/src/calibre/ebooks/oeb/transforms/flatcss.py b/src/calibre/ebooks/oeb/transforms/flatcss.py index c3b7f6f625..d3c490567e 100644 --- a/src/calibre/ebooks/oeb/transforms/flatcss.py +++ b/src/calibre/ebooks/oeb/transforms/flatcss.py @@ -150,11 +150,13 @@ class CSSFlattener(object): self.filter_css = frozenset() if self.opts.filter_css: try: - self.filter_css = frozenset([x.strip().lower() for x in - self.opts.filter_css.split(',')]) + self.filter_css = {x.strip().lower() for x in + self.opts.filter_css.split(',')} except: self.oeb.log.warning('Failed to parse filter_css, ignoring') else: + from calibre.ebooks.oeb.normalize_css import normalize_filter_css + self.filter_css = frozenset(normalize_filter_css(self.filter_css)) self.oeb.log.debug('Filtering CSS properties: %s'% ', '.join(self.filter_css))