mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Conversion: Fix normalization of CSS shorthand font property not working when multiple font families are specified in the same shorthand property
This commit is contained in:
parent
8440f1603b
commit
97c59cc1ec
@ -113,7 +113,7 @@ def normalize_simple_composition(name, cssvalue, composition, check_inherit=True
|
|||||||
|
|
||||||
font_composition = ('font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', 'font-family')
|
font_composition = ('font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', 'font-family')
|
||||||
|
|
||||||
def normalize_font(name, cssvalue):
|
def normalize_font(cssvalue, font_family_as_list=False):
|
||||||
# See https://developer.mozilla.org/en-US/docs/Web/CSS/font
|
# See https://developer.mozilla.org/en-US/docs/Web/CSS/font
|
||||||
composition = font_composition
|
composition = font_composition
|
||||||
val = cssvalue.cssText
|
val = cssvalue.cssText
|
||||||
@ -121,28 +121,44 @@ def normalize_font(name, cssvalue):
|
|||||||
return {k:'inherit' for k in composition}
|
return {k:'inherit' for k in composition}
|
||||||
if val in {'caption', 'icon', 'menu', 'message-box', 'small-caption', 'status-bar'}:
|
if val in {'caption', 'icon', 'menu', 'message-box', 'small-caption', 'status-bar'}:
|
||||||
return {k:DEFAULTS[k] for k in composition}
|
return {k:DEFAULTS[k] for k in composition}
|
||||||
try:
|
if getattr(cssvalue, 'length', 1) < 2:
|
||||||
primitives = list(v.cssText for v in cssvalue)
|
|
||||||
except TypeError:
|
|
||||||
primitives = [cssvalue.cssText]
|
|
||||||
if len(primitives) < 2:
|
|
||||||
return {} # Mandatory to define both font size and font family
|
return {} # Mandatory to define both font size and font family
|
||||||
style = {k:DEFAULTS[k] for k in composition}
|
style = {k:DEFAULTS[k] for k in composition}
|
||||||
style['font-family'] = primitives.pop()
|
families = []
|
||||||
if len(primitives) > 1 and cssprofiles.validate('line-height', primitives[-1]) and cssprofiles.validate('font-size', primitives[-2]):
|
vals = [x.cssText for x in cssvalue]
|
||||||
style['line-height'], style['font-size'] = primitives.pop(), primitives.pop()
|
found_font_size = False
|
||||||
else:
|
while vals:
|
||||||
val = primitives.pop()
|
text = vals.pop()
|
||||||
if not cssprofiles.validate('font-size', val):
|
if not families and text == 'inherit':
|
||||||
return {}
|
families.append(text)
|
||||||
style['font-size'] = val
|
continue
|
||||||
composition = composition[:3]
|
if cssprofiles.validate('font-size', text):
|
||||||
while primitives:
|
style['font-size'] = text
|
||||||
value = primitives.pop()
|
found_font_size = True
|
||||||
for key in composition:
|
break
|
||||||
if cssprofiles.validate(key, value):
|
if cssprofiles.validate('line-height', text):
|
||||||
style[key] = value
|
style['line-height'] = text
|
||||||
|
if not vals or not cssprofiles.validate('font-size', vals[-1]):
|
||||||
|
return {} # must have font-size here
|
||||||
|
style['font-size'] = vals.pop()
|
||||||
|
found_font_size = True
|
||||||
|
break
|
||||||
|
if families == ['inherit']:
|
||||||
|
return {} # Cannot have multiple font-families if the last one if inherit
|
||||||
|
families.insert(0, text)
|
||||||
|
if not families or not found_font_size:
|
||||||
|
return {} # font-family required
|
||||||
|
style['font-family'] = families if font_family_as_list else ', '.join(families)
|
||||||
|
props = ['font-style', 'font-variant', 'font-weight']
|
||||||
|
while vals:
|
||||||
|
for i, prop in enumerate(tuple(props)):
|
||||||
|
if cssprofiles.validate(prop, vals[0]):
|
||||||
|
props.pop(i)
|
||||||
|
style[prop] = vals.pop(0)
|
||||||
break
|
break
|
||||||
|
else:
|
||||||
|
return {} # unrecognized value
|
||||||
|
|
||||||
return style
|
return style
|
||||||
|
|
||||||
def normalize_border(name, cssvalue):
|
def normalize_border(name, cssvalue):
|
||||||
@ -154,7 +170,7 @@ def normalize_border(name, cssvalue):
|
|||||||
|
|
||||||
normalizers = {
|
normalizers = {
|
||||||
'list-style': simple_normalizer('list-style', ('type', 'position', 'image')),
|
'list-style': simple_normalizer('list-style', ('type', 'position', 'image')),
|
||||||
'font': normalize_font,
|
'font': lambda prop, v: normalize_font(v),
|
||||||
'border': normalize_border,
|
'border': normalize_border,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +284,7 @@ def test_normalization(): # {{{
|
|||||||
|
|
||||||
def test_font_normalization(self):
|
def test_font_normalization(self):
|
||||||
def font_dict(expected):
|
def font_dict(expected):
|
||||||
ans = {k:DEFAULTS[k] for k in font_composition}
|
ans = {k:DEFAULTS[k] for k in font_composition} if expected else {}
|
||||||
ans.update(expected)
|
ans.update(expected)
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
@ -276,6 +292,7 @@ def test_normalization(): # {{{
|
|||||||
'some_font': {}, 'none': {}, 'inherit':{k:'inherit' for k in font_composition},
|
'some_font': {}, 'none': {}, 'inherit':{k:'inherit' for k in font_composition},
|
||||||
'1.2pt/1.4 A_Font': {'font-family':'A_Font', 'font-size':'1.2pt', 'line-height':'1.4'},
|
'1.2pt/1.4 A_Font': {'font-family':'A_Font', 'font-size':'1.2pt', 'line-height':'1.4'},
|
||||||
'bad font': {}, '10% serif': {'font-family':'serif', 'font-size':'10%'},
|
'bad font': {}, '10% serif': {'font-family':'serif', 'font-size':'10%'},
|
||||||
|
'12px "My Font", serif': {'font-family':'"My Font", serif', 'font-size': '12px'},
|
||||||
'bold italic large serif': {'font-family':'serif', 'font-weight':'bold', 'font-style':'italic', 'font-size':'large'},
|
'bold italic large serif': {'font-family':'serif', 'font-weight':'bold', 'font-style':'italic', 'font-size':'large'},
|
||||||
'bold italic small-caps larger/normal serif':
|
'bold italic small-caps larger/normal serif':
|
||||||
{'font-family':'serif', 'font-weight':'bold', 'font-style':'italic', 'font-size':'larger',
|
{'font-family':'serif', 'font-weight':'bold', 'font-style':'italic', 'font-size':'larger',
|
||||||
@ -283,10 +300,7 @@ def test_normalization(): # {{{
|
|||||||
}.iteritems():
|
}.iteritems():
|
||||||
val = tuple(parseStyle('font: %s' % raw, validate=False))[0].cssValue
|
val = tuple(parseStyle('font: %s' % raw, validate=False))[0].cssValue
|
||||||
style = normalizers['font']('font', val)
|
style = normalizers['font']('font', val)
|
||||||
if expected:
|
self.assertDictEqual(font_dict(expected), style, raw)
|
||||||
self.assertDictEqual(font_dict(expected), style)
|
|
||||||
else:
|
|
||||||
self.assertDictEqual(expected, style)
|
|
||||||
|
|
||||||
def test_border_normalization(self):
|
def test_border_normalization(self):
|
||||||
def border_edge_dict(expected, edge='right'):
|
def border_edge_dict(expected, edge='right'):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user