diff --git a/src/calibre/ebooks/oeb/polish/cascade.py b/src/calibre/ebooks/oeb/polish/cascade.py index 35baa9af0b..677c693a67 100644 --- a/src/calibre/ebooks/oeb/polish/cascade.py +++ b/src/calibre/ebooks/oeb/polish/cascade.py @@ -63,7 +63,7 @@ def iterrules(container, rules, sheet_name, media_rule_ok=media_allowed, rule_in num = next(rule_index_counter) yield rule, sheet_name, num -StyleDeclaration = namedtuple('StyleDeclaration', 'index sheet_name declaration pseudo_element') +StyleDeclaration = namedtuple('StyleDeclaration', 'index declaration pseudo_element') Specificity = namedtuple('Specificity', 'is_style num_id num_class num_elem rule_index') def specificity(rule_index, selector, is_style=0): @@ -78,29 +78,39 @@ def iterdeclaration(decl): else: for k, v in n(p.name, p.propertyValue).iteritems(): yield Property(k, v, p.literalpriority) +class Values(tuple): -def normalize_style_declaration(decl): + ''' A tuple of `cssutils.css.Value ` (and its subclasses) objects. Also has a + `sheet_name` attribute that is the canonical name relative to which URLs + for this property should be resolved. ''' + + def __new__(typ, pv, sheet_name=None, priority=''): + ans = tuple.__new__(typ, pv) + ans.sheet_name = sheet_name + ans.is_important = priority == 'important' + return ans + +def normalize_style_declaration(decl, sheet_name): ans = {} for prop in iterdeclaration(decl): - ans[prop.name] = (prop.propertyValue, prop.priority) + ans[prop.name] = Values(prop.propertyValue, sheet_name, prop.priority) return ans def resolve_declarations(decls): property_names = set() - for decl in decls: - property_names |= set(decl) + for d in decls: + property_names |= set(d.declaration) ans = {} for name in property_names: first_val = None for decl in decls: - x = decl.get(name) + x = decl.declaration.get(name) if x is not None: - val, priority = x - if priority == 'important': - first_val = val + if x.is_important: + first_val = x break if first_val is None: - first_val = val + first_val = x ans[name] = first_val return ans @@ -122,13 +132,13 @@ def resolve_styles(container, name): container.log.error('Ignoring CSS rule with invalid selector: %r (%s)' % (text, as_unicode(err))) continue m = pseudo_pat.search(text) - style = normalize_style_declaration(rule.style) + style = normalize_style_declaration(rule.style, sheet_name) if m is None: for elem in matches: - style_map[elem].append(StyleDeclaration(specificity(rule_index, selector), sheet_name, style, None)) + style_map[elem].append(StyleDeclaration(specificity(rule_index, selector), style, None)) else: for elem in matches: - pseudo_style_map[elem].append(StyleDeclaration(specificity(rule_index, selector), sheet_name, style, m.group(1))) + pseudo_style_map[elem].append(StyleDeclaration(specificity(rule_index, selector), style, m.group(1))) process_sheet(html_css_stylesheet(), 'user-agent.css') @@ -158,7 +168,7 @@ def resolve_styles(container, name): text = elem.get('style') if text: style = container.parse_css(text, is_declaration=True) - style_map[elem].append(StyleDeclaration(Specificity(1, 0, 0, 0, 0), name, normalize_style_declaration(style), None)) + style_map[elem].append(StyleDeclaration(Specificity(1, 0, 0, 0, 0), normalize_style_declaration(style, name), None)) for l in (style_map, pseudo_style_map): for x in l.itervalues(): @@ -175,14 +185,14 @@ def defvals(): global _defvals if _defvals is None: u = type('') - _defvals = {k:Property(k, u(val)).propertyValue for k, val in DEFAULTS.iteritems()} + _defvals = {k:Values(Property(k, u(val)).propertyValue) for k, val in DEFAULTS.iteritems()} return _defvals def get_resolved_property(elem, name, style_map): ''' Given a `style_map` previously generated by :func:`resolve_styles()` and a property `name`, returns the effective value of that property for the specified element. Handles inheritance and CSS cascading rules. Returns - an instance of `cssutils.css.PropertyValue`. If the property was never set and + an instance of :class:`Values`. If the property was never set and is not a known property, then it will return None. ''' inheritable = name in INHERITED