mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
Function to resolve pseudo-element properties
This commit is contained in:
parent
91c85b351c
commit
a853e4dac0
@ -137,6 +137,12 @@ def resolve_declarations(decls):
|
|||||||
ans[name] = first_val
|
ans[name] = first_val
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
def resolve_pseudo_declarations(decls):
|
||||||
|
groups = defaultdict(list)
|
||||||
|
for d in decls:
|
||||||
|
groups[d.pseudo_element].append(d)
|
||||||
|
return {k:resolve_declarations(v) for k, v in groups.iteritems()}
|
||||||
|
|
||||||
def resolve_styles(container, name, select=None, sheet_callback=None):
|
def resolve_styles(container, name, select=None, sheet_callback=None):
|
||||||
root = container.parsed(name)
|
root = container.parsed(name)
|
||||||
select = select or Select(root, ignore_inappropriate_pseudo_classes=True)
|
select = select or Select(root, ignore_inappropriate_pseudo_classes=True)
|
||||||
@ -200,7 +206,7 @@ def resolve_styles(container, name, select=None, sheet_callback=None):
|
|||||||
x.sort(key=itemgetter(0), reverse=True)
|
x.sort(key=itemgetter(0), reverse=True)
|
||||||
|
|
||||||
style_map = {elem:resolve_declarations(x) for elem, x in style_map.iteritems()}
|
style_map = {elem:resolve_declarations(x) for elem, x in style_map.iteritems()}
|
||||||
pseudo_style_map = {elem:resolve_declarations(x) for elem, x in pseudo_style_map.iteritems()}
|
pseudo_style_map = {elem:resolve_pseudo_declarations(x) for elem, x in pseudo_style_map.iteritems()}
|
||||||
|
|
||||||
return style_map, pseudo_style_map, select
|
return style_map, pseudo_style_map, select
|
||||||
|
|
||||||
@ -230,3 +236,13 @@ def resolve_property(elem, name, style_map):
|
|||||||
return val
|
return val
|
||||||
q = q.getparent() if inheritable else None
|
q = q.getparent() if inheritable else None
|
||||||
return defvals().get(name)
|
return defvals().get(name)
|
||||||
|
|
||||||
|
def resolve_pseudo_property(elem, prop, name, pseudo_style_map):
|
||||||
|
style_map = pseudo_style_map.get(elem)
|
||||||
|
if style_map is not None:
|
||||||
|
prop_map = style_map.get(prop)
|
||||||
|
if prop_map is not None:
|
||||||
|
val = prop_map.get(name)
|
||||||
|
if val is not None:
|
||||||
|
return val
|
||||||
|
return defvals().get(name)
|
||||||
|
@ -10,7 +10,7 @@ from functools import partial
|
|||||||
|
|
||||||
from calibre.constants import iswindows
|
from calibre.constants import iswindows
|
||||||
from calibre.ebooks.oeb.base import OEB_STYLES, OEB_DOCS
|
from calibre.ebooks.oeb.base import OEB_STYLES, OEB_DOCS
|
||||||
from calibre.ebooks.oeb.polish.cascade import iterrules, resolve_property, resolve_styles, DEFAULTS
|
from calibre.ebooks.oeb.polish.cascade import iterrules, resolve_property, resolve_styles, DEFAULTS, resolve_pseudo_property
|
||||||
from calibre.ebooks.oeb.polish.container import ContainerBase, href_to_name
|
from calibre.ebooks.oeb.polish.container import ContainerBase, href_to_name
|
||||||
from calibre.ebooks.oeb.polish.tests.base import BaseTest
|
from calibre.ebooks.oeb.polish.tests.base import BaseTest
|
||||||
from calibre.utils.logging import Log, Stream
|
from calibre.utils.logging import Log, Stream
|
||||||
@ -72,10 +72,20 @@ class CascadeTest(BaseTest):
|
|||||||
val = type('')(DEFAULTS[name])
|
val = type('')(DEFAULTS[name])
|
||||||
self.assertEqual(val, ans.cssText)
|
self.assertEqual(val, ans.cssText)
|
||||||
|
|
||||||
def get_maps(html, styles=None):
|
def test_pseudo_property(select, pseudo_style_map, selector, prop, name, val=None):
|
||||||
|
elem = next(select(selector))
|
||||||
|
ans = resolve_pseudo_property(elem, prop, name, pseudo_style_map)
|
||||||
|
if val is None:
|
||||||
|
val = type('')(DEFAULTS[name])
|
||||||
|
self.assertEqual(val, ans.cssText)
|
||||||
|
|
||||||
|
def get_maps(html, styles=None, pseudo=False):
|
||||||
html = '<html><head><link href="styles.css"></head><body>{}</body></html>'.format(html)
|
html = '<html><head><link href="styles.css"></head><body>{}</body></html>'.format(html)
|
||||||
c = VirtualContainer({'index.html':html, 'styles.css':styles or 'body { color: red; font-family: "Kovid Goyal", sans-serif }'})
|
c = VirtualContainer({'index.html':html, 'styles.css':styles or 'body { color: red; font-family: "Kovid Goyal", sans-serif }'})
|
||||||
style_map, pseudo_style_map, select = resolve_styles(c, 'index.html')
|
style_map, pseudo_style_map, select = resolve_styles(c, 'index.html')
|
||||||
|
if pseudo:
|
||||||
|
tp = partial(test_pseudo_property, select, pseudo_style_map)
|
||||||
|
else:
|
||||||
tp = partial(test_property, select, style_map)
|
tp = partial(test_property, select, style_map)
|
||||||
return tp
|
return tp
|
||||||
|
|
||||||
@ -104,3 +114,12 @@ class CascadeTest(BaseTest):
|
|||||||
t('p', 'color', 'blue')
|
t('p', 'color', 'blue')
|
||||||
t = get_maps('<p>xxx</p><style>p {color: blue}</style>', 'p {color: red; margin:11pt}')
|
t = get_maps('<p>xxx</p><style>p {color: blue}</style>', 'p {color: red; margin:11pt}')
|
||||||
t('p', 'margin-top', '11pt')
|
t('p', 'margin-top', '11pt')
|
||||||
|
t = get_maps('<p></p>', 'p:before { content: "xxx" }', True)
|
||||||
|
t('p', 'before', 'content', '"xxx"')
|
||||||
|
t = get_maps('<p></p>', 'body p:before { content: "xxx" } p:before { content: "yyy" }', True)
|
||||||
|
t('p', 'before', 'content', '"xxx"')
|
||||||
|
t = get_maps('<p></p>', "p:before { content: 'xxx' } p:first-letter { font-weight: bold }", True)
|
||||||
|
t('p', 'before', 'content', '"xxx"')
|
||||||
|
t('p', 'first-letter', 'font-weight', 'bold')
|
||||||
|
t = get_maps('<p></p>', 'p:before { content: xxx }', True)
|
||||||
|
t('p', 'before', 'content', 'xxx')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user