mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Subsetting: Handle child elements under ::first-line
This commit is contained in:
parent
9bdfb5bf46
commit
f1cc7ddfd9
@ -253,7 +253,17 @@ def resolve_property(style_map, elem, name):
|
|||||||
return defvals().get(name)
|
return defvals().get(name)
|
||||||
|
|
||||||
|
|
||||||
def resolve_pseudo_property(style_map, pseudo_style_map, elem, prop, name, abort_on_missing=False):
|
def resolve_pseudo_property(style_map, pseudo_style_map, elem, prop, name, abort_on_missing=False, check_if_pseudo_applies=False, check_ancestors=False):
|
||||||
|
if check_if_pseudo_applies:
|
||||||
|
q = elem
|
||||||
|
while q is not None:
|
||||||
|
val = pseudo_style_map.get(q, {}).get(prop, {}).get(name)
|
||||||
|
if val is not None:
|
||||||
|
return True
|
||||||
|
if not check_ancestors:
|
||||||
|
break
|
||||||
|
q = q.getparent()
|
||||||
|
return False
|
||||||
sub_map = pseudo_style_map.get(elem)
|
sub_map = pseudo_style_map.get(elem)
|
||||||
if abort_on_missing and sub_map is None:
|
if abort_on_missing and sub_map is None:
|
||||||
return None
|
return None
|
||||||
@ -266,5 +276,14 @@ def resolve_pseudo_property(style_map, pseudo_style_map, elem, prop, name, abort
|
|||||||
if val is not None:
|
if val is not None:
|
||||||
return val
|
return val
|
||||||
if name in INHERITED:
|
if name in INHERITED:
|
||||||
|
if check_ancestors:
|
||||||
|
q = elem.getparent()
|
||||||
|
while q is not None:
|
||||||
|
val = pseudo_style_map.get(q, {}).get(prop, {}).get(name)
|
||||||
|
if val is not None:
|
||||||
|
return val
|
||||||
|
if not check_ancestors:
|
||||||
|
break
|
||||||
|
q = q.getparent()
|
||||||
return resolve_property(style_map, elem, name)
|
return resolve_property(style_map, elem, name)
|
||||||
return defvals().get(name)
|
return defvals().get(name)
|
||||||
|
@ -249,8 +249,7 @@ class StatsCollector:
|
|||||||
update_usage_for_embed(font, chars)
|
update_usage_for_embed(font, chars)
|
||||||
for rule in get_matching_rules(font_face_rules, font):
|
for rule in get_matching_rules(font_face_rules, font):
|
||||||
self.font_stats[rule['src']] |= chars
|
self.font_stats[rule['src']] |= chars
|
||||||
q = resolve_pseudo_property(elem, 'first-letter', 'font-family', abort_on_missing=True)
|
if resolve_pseudo_property(elem, 'first-letter', 'font-family', check_if_pseudo_applies=True):
|
||||||
if q is not None:
|
|
||||||
font = get_font_dict(elem, resolve_pseudo_property, pseudo='first-letter')
|
font = get_font_dict(elem, resolve_pseudo_property, pseudo='first-letter')
|
||||||
text = get_element_text(elem, resolve_property, resolve_pseudo_property, self.capitalize_pat, for_pseudo='first-letter')
|
text = get_element_text(elem, resolve_property, resolve_pseudo_property, self.capitalize_pat, for_pseudo='first-letter')
|
||||||
m = self.first_letter_pat.search(text.lstrip())
|
m = self.first_letter_pat.search(text.lstrip())
|
||||||
@ -259,9 +258,8 @@ class StatsCollector:
|
|||||||
update_usage_for_embed(font, chars)
|
update_usage_for_embed(font, chars)
|
||||||
for rule in get_matching_rules(font_face_rules, font):
|
for rule in get_matching_rules(font_face_rules, font):
|
||||||
self.font_stats[rule['src']] |= chars
|
self.font_stats[rule['src']] |= chars
|
||||||
q = resolve_pseudo_property(elem, 'first-line', 'font-family', abort_on_missing=True)
|
if resolve_pseudo_property(elem, 'first-line', 'font-family', check_if_pseudo_applies=True, check_ancestors=True):
|
||||||
if q is not None:
|
font = get_font_dict(elem, partial(resolve_pseudo_property, check_ancestors=True), pseudo='first-line')
|
||||||
font = get_font_dict(elem, resolve_pseudo_property, pseudo='first-line')
|
|
||||||
text = get_element_text(elem, resolve_property, resolve_pseudo_property, self.capitalize_pat, for_pseudo='first-line')
|
text = get_element_text(elem, resolve_property, resolve_pseudo_property, self.capitalize_pat, for_pseudo='first-line')
|
||||||
chars = frozenset(ord_string(text)) - exclude_chars
|
chars = frozenset(ord_string(text)) - exclude_chars
|
||||||
update_usage_for_embed(font, chars)
|
update_usage_for_embed(font, chars)
|
||||||
|
@ -160,7 +160,6 @@ class CascadeTest(BaseTest):
|
|||||||
v = 'url(%s)' % v
|
v = 'url(%s)' % v
|
||||||
styles.append(f'{k} : {v};')
|
styles.append(f'{k} : {v};')
|
||||||
styles.append('}\n')
|
styles.append('}\n')
|
||||||
html = f'<html><head><link href="styles.css"></head><body>{html}</body></html>'
|
|
||||||
files['styles.css'] = embeds + '\n'.join(styles)
|
files['styles.css'] = embeds + '\n'.join(styles)
|
||||||
c = VirtualContainer(files)
|
c = VirtualContainer(files)
|
||||||
return StatsCollector(c, do_embed=True)
|
return StatsCollector(c, do_embed=True)
|
||||||
@ -207,6 +206,9 @@ class CascadeTest(BaseTest):
|
|||||||
|
|
||||||
s = get_stats('<p style="font-family: X; text-transform:uppercase">abc</p><b style="font-family: X; font-variant: small-caps">d\nef</b>')
|
s = get_stats('<p style="font-family: X; text-transform:uppercase">abc</p><b style="font-family: X; font-variant: small-caps">d\nef</b>')
|
||||||
self.assertEqual(s.font_stats, {'XB.otf':set('defDEF'), 'X.otf':set('ABC')})
|
self.assertEqual(s.font_stats, {'XB.otf':set('defDEF'), 'X.otf':set('ABC')})
|
||||||
|
s = get_stats('<style>.fl::first-line { font-family: X }</style><p class="fl">abc<b>def</b></p>')
|
||||||
|
# Technically def should not be needed in X but that is hard to achieve
|
||||||
|
self.assertEqual(s.font_stats, {'XB.otf':set('def'), 'X.otf':set('abcdef')})
|
||||||
|
|
||||||
def test_remove_property_value(self):
|
def test_remove_property_value(self):
|
||||||
style = parseStyle('background-image: url(b.png); background: black url(a.png) fixed')
|
style = parseStyle('background-image: url(b.png); background: black url(a.png) fixed')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user