MOBI Output: Fix invalid color specification as plain numbers causing conversion to fail. Fixes #1933797 [ebook-convert fails with TypeError: Argument must be bytes or unicode, got 'float'](https://bugs.launchpad.net/calibre/+bug/1933797)

More generally have the conversion pipeline validate values for color
just as it does for background-color
This commit is contained in:
Kovid Goyal 2021-06-28 14:19:48 +05:30
parent 582e13ba6e
commit 47ec4b5521
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 19 additions and 9 deletions

View File

@ -640,7 +640,7 @@ def is_guide_ref_start(ref):
def convert_color_for_font_tag(val): def convert_color_for_font_tag(val):
rgba = parse_color_string(unicode_type(val or '')) rgba = parse_color_string(unicode_type(val or ''))
if rgba is None or rgba == 'currentColor': if rgba is None or rgba == 'currentColor':
return val return str(val)
clamp = lambda x: min(x, max(0, x), 1) clamp = lambda x: min(x, max(0, x), 1)
rgb = map(clamp, rgba[:3]) rgb = map(clamp, rgba[:3])
return '#' + ''.join(map(lambda x:'%02x' % int(x * 255), rgb)) return '#' + ''.join(map(lambda x:'%02x' % int(x * 255), rgb))

View File

@ -29,6 +29,12 @@ css_parser_log.setLevel(logging.WARN)
_html_css_stylesheet = None _html_css_stylesheet = None
def validate_color(col):
return cssprofiles.validateWithProfile('color',
col,
profiles=[profiles.Profiles.CSS_LEVEL_2])[1]
def html_css_stylesheet(): def html_css_stylesheet():
global _html_css_stylesheet global _html_css_stylesheet
if _html_css_stylesheet is None: if _html_css_stylesheet is None:
@ -414,6 +420,7 @@ class Style(object):
self._height = None self._height = None
self._lineHeight = None self._lineHeight = None
self._bgcolor = None self._bgcolor = None
self._fgcolor = None
self._pseudo_classes = {} self._pseudo_classes = {}
stylizer._styles[element] = self stylizer._styles[element] = self
@ -467,9 +474,7 @@ class Style(object):
return self._unit_convert(self._get(name)) return self._unit_convert(self._get(name))
def _get(self, name): def _get(self, name):
result = None result = self._style.get(name, None)
if name in self._style:
result = self._style[name]
if (result == 'inherit' or (result is None and name in INHERITED and self._has_parent())): if (result == 'inherit' or (result is None and name in INHERITED and self._has_parent())):
stylizer = self._stylizer stylizer = self._stylizer
result = stylizer.style(self._element.getparent())._get(name) result = stylizer.style(self._element.getparent())._get(name)
@ -491,6 +496,16 @@ class Style(object):
def pt_to_px(self, value): def pt_to_px(self, value):
return (self._profile.dpi / 72) * value return (self._profile.dpi / 72) * value
@property
def color(self):
if self._fgcolor is None:
val = self._get('color')
if val and validate_color(val):
self._fgcolor = val
else:
self._fgcolor = DEFAULTS['color']
return self._fgcolor
@property @property
def backgroundColor(self): def backgroundColor(self):
''' '''
@ -499,11 +514,6 @@ class Style(object):
are not used. None is returned if no background color is set. are not used. None is returned if no background color is set.
''' '''
def validate_color(col):
return cssprofiles.validateWithProfile('color',
col,
profiles=[profiles.Profiles.CSS_LEVEL_2])[1]
if self._bgcolor is None: if self._bgcolor is None:
col = None col = None
val = self._style.get('background-color', None) val = self._style.get('background-color', None)