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:
Kovid Goyal 2014-06-10 21:25:56 +05:30
parent 8440f1603b
commit 97c59cc1ec

View File

@ -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')
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
composition = font_composition
val = cssvalue.cssText
@ -121,28 +121,44 @@ def normalize_font(name, cssvalue):
return {k:'inherit' for k in composition}
if val in {'caption', 'icon', 'menu', 'message-box', 'small-caption', 'status-bar'}:
return {k:DEFAULTS[k] for k in composition}
try:
primitives = list(v.cssText for v in cssvalue)
except TypeError:
primitives = [cssvalue.cssText]
if len(primitives) < 2:
if getattr(cssvalue, 'length', 1) < 2:
return {} # Mandatory to define both font size and font family
style = {k:DEFAULTS[k] for k in composition}
style['font-family'] = primitives.pop()
if len(primitives) > 1 and cssprofiles.validate('line-height', primitives[-1]) and cssprofiles.validate('font-size', primitives[-2]):
style['line-height'], style['font-size'] = primitives.pop(), primitives.pop()
else:
val = primitives.pop()
if not cssprofiles.validate('font-size', val):
return {}
style['font-size'] = val
composition = composition[:3]
while primitives:
value = primitives.pop()
for key in composition:
if cssprofiles.validate(key, value):
style[key] = value
families = []
vals = [x.cssText for x in cssvalue]
found_font_size = False
while vals:
text = vals.pop()
if not families and text == 'inherit':
families.append(text)
continue
if cssprofiles.validate('font-size', text):
style['font-size'] = text
found_font_size = True
break
if cssprofiles.validate('line-height', text):
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
else:
return {} # unrecognized value
return style
def normalize_border(name, cssvalue):
@ -154,7 +170,7 @@ def normalize_border(name, cssvalue):
normalizers = {
'list-style': simple_normalizer('list-style', ('type', 'position', 'image')),
'font': normalize_font,
'font': lambda prop, v: normalize_font(v),
'border': normalize_border,
}
@ -268,7 +284,7 @@ def test_normalization(): # {{{
def test_font_normalization(self):
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)
return ans
@ -276,6 +292,7 @@ def test_normalization(): # {{{
'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'},
'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 small-caps larger/normal serif':
{'font-family':'serif', 'font-weight':'bold', 'font-style':'italic', 'font-size':'larger',
@ -283,10 +300,7 @@ def test_normalization(): # {{{
}.iteritems():
val = tuple(parseStyle('font: %s' % raw, validate=False))[0].cssValue
style = normalizers['font']('font', val)
if expected:
self.assertDictEqual(font_dict(expected), style)
else:
self.assertDictEqual(expected, style)
self.assertDictEqual(font_dict(expected), style, raw)
def test_border_normalization(self):
def border_edge_dict(expected, edge='right'):