From 9d984ba7e423084b658adaee0b46b44575dd0c0a Mon Sep 17 00:00:00 2001 From: David Barbarisi Date: Wed, 9 Sep 2015 16:37:38 -0400 Subject: [PATCH] Adds a remove_unset_properties setting. Squashed commits. --- premailer/merge_style.py | 23 ++++++++++++--- premailer/premailer.py | 17 ++++++++--- premailer/tests/test_premailer.py | 48 +++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 8 deletions(-) diff --git a/premailer/merge_style.py b/premailer/merge_style.py index 4730768..0fe93f7 100644 --- a/premailer/merge_style.py +++ b/premailer/merge_style.py @@ -19,7 +19,12 @@ def csstext_to_pairs(csstext): csstext_to_pairs._lock = threading.RLock() -def merge_styles(inline_style, new_styles, classes): +def merge_styles( + inline_style, + new_styles, + classes, + remove_unset_properties=False +): """ This will merge all new styles where the order is important The last one will override the first @@ -29,9 +34,12 @@ def merge_styles(inline_style, new_styles, classes): Args: inline_style(str): the old inline style of the element if there - is one new_styles: a list of new styles, each element should be - a list of tuple classes: a list of classes which maps - new_styles, important! + is one + new_styles: a list of new styles, each element should be + a list of tuple + classes: a list of classes which maps new_styles, important! + remove_unset_properties(bool): Allow us to remove certain CSS + properties with rules that set their value to 'unset' Returns: str: the final style @@ -55,6 +63,13 @@ def merge_styles(inline_style, new_styles, classes): normal_styles = [] pseudo_styles = [] for pseudoclass, kv in styles.items(): + if remove_unset_properties: + # Remove rules that we were going to have value 'unset' because + # they effectively are the same as not saying anything about the + # property when inlined + kv = dict( + (k, v) for (k, v) in kv.items() if not v.lower() == 'unset' + ) if not kv: continue if pseudoclass: diff --git a/premailer/premailer.py b/premailer/premailer.py index 9e2abb8..76736b3 100644 --- a/premailer/premailer.py +++ b/premailer/premailer.py @@ -115,7 +115,8 @@ class Premailer(object): cssutils_logging_handler=None, cssutils_logging_level=None, disable_leftover_css=False, - align_floating_images=True): + align_floating_images=True, + remove_unset_properties=True): self.html = html self.base_url = base_url self.preserve_internal_links = preserve_internal_links @@ -143,6 +144,7 @@ class Premailer(object): self.cache_css_parsing = cache_css_parsing self.disable_leftover_css = disable_leftover_css self.align_floating_images = align_floating_images + self.remove_unset_properties = remove_unset_properties if cssutils_logging_handler: cssutils.log.addHandler(cssutils_logging_handler) @@ -396,9 +398,16 @@ class Premailer(object): # crucial when you have a lot of pseudo/classes # and a long list of elements for _, element in elements.items(): - final_style = merge_styles(element['item'].attrib.get('style', ''), - element['style'], element['classes']) - element['item'].attrib['style'] = final_style + final_style = merge_styles( + element['item'].attrib.get('style', ''), + element['style'], + element['classes'], + remove_unset_properties=self.remove_unset_properties, + ) + if final_style: + # final style could be empty string because of + # remove_unset_properties + element['item'].attrib['style'] = final_style self._style_to_basic_html_attributes( element['item'], final_style, diff --git a/premailer/tests/test_premailer.py b/premailer/tests/test_premailer.py index ca8416b..9adf49b 100644 --- a/premailer/tests/test_premailer.py +++ b/premailer/tests/test_premailer.py @@ -143,6 +143,21 @@ class Tests(unittest.TestCase): for each in expect: ok_(each in result) + def test_merge_styles_with_unset(self): + inline_style = 'color: red' + new = 'font-size: 10px; font-size: unset; font-weight: bold' + expect = 'color:red;', 'font-weight:bold' + css_new = csstext_to_pairs(new) + result = merge_styles( + inline_style, + [css_new], + [''], + remove_unset_properties=True, + ) + for each in expect: + ok_(each in result) + ok_('font-size' not in result) + def test_basic_html(self): """test the simplest case""" @@ -2453,3 +2468,36 @@ sheet" type="text/css"> p = Premailer(html, align_floating_images=True) result_html = p.transform() compare_html(expect_html, result_html) + + def test_remove_unset_properties(self): + html = """ + + + + +
+ + """ + + expect_html = """ + + + +
+ + """ + + p = Premailer(html, remove_unset_properties=True) + self.assertTrue(p.remove_unset_properties) + result_html = p.transform() + compare_html(expect_html, result_html)