Add an option to capitalize margin and float properties
The option is disabled by default, that weird idea comes from a weird outlook.com behaviour to handle margin and float properties only if the first letter is uppercase. See https://www.emailonacid.com/blog/article/email-development/outlook.com-does-support-margins
This commit is contained in:
parent
50d0719ce6
commit
27ac936a22
|
@ -64,6 +64,12 @@ def main(args):
|
|||
action="store_true", dest="remove_classes"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--capitalize-float-margin", default=False,
|
||||
help="Capitalize float and margin properties for outlook.com compat.",
|
||||
action="store_true", dest="capitalize_float_margin"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--strip-important", default=False,
|
||||
help="Remove '!important' for all css declarations.",
|
||||
|
|
|
@ -85,8 +85,27 @@ def _cache_parse_css_string(css_body, validate=True):
|
|||
"""
|
||||
return cssutils.parseString(css_body, validate=validate)
|
||||
|
||||
|
||||
def capitalize_float_margin(css_body):
|
||||
"""Capitalize float and margin CSS property names
|
||||
"""
|
||||
def _capitalize_property(match):
|
||||
return '{0}:{1}{2}'.format(
|
||||
match.group('property').capitalize(),
|
||||
match.group('value'),
|
||||
match.group('terminator'))
|
||||
|
||||
return _lowercase_margin_float_rule.sub(_capitalize_property, css_body)
|
||||
|
||||
|
||||
_element_selector_regex = re.compile(r'(^|\s)\w')
|
||||
_cdata_regex = re.compile(r'\<\!\[CDATA\[(.*?)\]\]\>', re.DOTALL)
|
||||
_lowercase_margin_float_rule = re.compile(
|
||||
r'''(?P<property>margin(-(top|bottom|left|right))?|float)
|
||||
:
|
||||
(?P<value>.*?)
|
||||
(?P<terminator>$|;)''',
|
||||
re.IGNORECASE | re.VERBOSE)
|
||||
_importants = re.compile('\s*!important')
|
||||
# These selectors don't apply to all elements. Rather, they specify
|
||||
# which elements to apply to.
|
||||
|
@ -104,6 +123,7 @@ class Premailer(object):
|
|||
keep_style_tags=False,
|
||||
include_star_selectors=False,
|
||||
remove_classes=True,
|
||||
capitalize_float_margin=False,
|
||||
strip_important=True,
|
||||
external_styles=None,
|
||||
css_text=None,
|
||||
|
@ -126,6 +146,7 @@ class Premailer(object):
|
|||
# this will always preserve the original css
|
||||
self.keep_style_tags = keep_style_tags
|
||||
self.remove_classes = remove_classes
|
||||
self.capitalize_float_margin = capitalize_float_margin
|
||||
# whether to process or ignore selectors like '* { foo:bar; }'
|
||||
self.include_star_selectors = include_star_selectors
|
||||
if isinstance(external_styles, STR_TYPE):
|
||||
|
@ -420,6 +441,14 @@ class Premailer(object):
|
|||
parent = item.getparent()
|
||||
del parent.attrib['class']
|
||||
|
||||
# Capitalize Margin properties
|
||||
# To fix weird outlook bug
|
||||
# https://www.emailonacid.com/blog/article/email-development/outlook.com-does-support-margins
|
||||
if self.capitalize_float_margin:
|
||||
for item in page.xpath('//@style'):
|
||||
mangled = capitalize_float_margin(item)
|
||||
item.getparent().attrib['style'] = mangled
|
||||
|
||||
# Add align attributes to images if they have a CSS float value of
|
||||
# right or left. Outlook (both on desktop and on the web) are bad at
|
||||
# understanding floats, but they do understand the HTML align attrib.
|
||||
|
|
|
@ -16,9 +16,3 @@ class TestMergeStyle(unittest.TestCase):
|
|||
# Invalid syntax does not raise
|
||||
inline = '{color:pink} :hover{color:purple} :active{color:red}'
|
||||
merge_styles(inline, [], [])
|
||||
|
||||
def test_important_rule(self):
|
||||
# No exception after #133
|
||||
csstext = 'font-size:1px !important'
|
||||
parsed_csstext = csstext_to_pairs(csstext)
|
||||
self.assertEqual(('font-size', '1px'), parsed_csstext[0])
|
||||
|
|
|
@ -828,6 +828,45 @@ ical-align:middle" bgcolor="red" valign="middle">Cell 2</td>
|
|||
|
||||
compare_html(expect_html, result_html)
|
||||
|
||||
def test_uppercase_margin(self):
|
||||
"""Option to comply with outlook.com
|
||||
|
||||
https://emailonacid.com/blog/article/email-development/outlook.com-does-support-margins
|
||||
"""
|
||||
|
||||
html = """<html>
|
||||
<head>
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<style>
|
||||
h1 {margin: 0}
|
||||
h2 {margin-top:0;margin-bottom:0;margin-left:0;margin-right:0}
|
||||
</style>
|
||||
<body>
|
||||
<h1>a</h1>
|
||||
<h2>
|
||||
b
|
||||
</h2>
|
||||
</body>
|
||||
</html>"""
|
||||
|
||||
expect_html = """<html>
|
||||
<head>
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1 style="Margin:0">a</h1>
|
||||
<h2 style="Margin-bottom:0; Margin-left:0; Margin-right:0; Margin-top:0">
|
||||
b
|
||||
</h2>
|
||||
</body>
|
||||
</html>"""
|
||||
|
||||
p = Premailer(html, capitalize_float_margin=True)
|
||||
result_html = p.transform()
|
||||
|
||||
compare_html(expect_html, result_html)
|
||||
|
||||
def test_strip_important(self):
|
||||
"""Get rid of !important. Makes no sense inline."""
|
||||
html = """<html>
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import unittest
|
||||
|
||||
from premailer.premailer import capitalize_float_margin
|
||||
|
||||
|
||||
class UtilsTestCase(unittest.TestCase):
|
||||
def testcapitalize_float_margin(self):
|
||||
self.assertEqual(
|
||||
capitalize_float_margin('margin:1em'),
|
||||
'Margin:1em')
|
||||
self.assertEqual(
|
||||
capitalize_float_margin('margin-left:1em'),
|
||||
'Margin-left:1em')
|
||||
self.assertEqual(
|
||||
capitalize_float_margin('float:right;'),
|
||||
'Float:right;')
|
||||
self.assertEqual(
|
||||
capitalize_float_margin('float:right;color:red;margin:0'),
|
||||
'Float:right;color:red;Margin:0')
|
Loading…
Reference in New Issue