From 3d4f18b9168c06992ff2313df2c785e21c3f1713 Mon Sep 17 00:00:00 2001 From: Tontyna <35614937+Tontyna@users.noreply.github.com> Date: Thu, 17 Oct 2019 23:39:20 +0200 Subject: [PATCH] Add html element to Box class Unless the Box is a PageBox or a MarginBox the new attribute `element` points to the html element (xml.etree.ElementTree.Element) where the Box stems from. This enables e.g. post-processing that depends on Element attributes, like 'class' or 'id'. Caution: Elements with no subelements will test as False! Test the element's existence with `if box.element is not None:`. Related to #434, #970. --- weasyprint/formatting_structure/boxes.py | 21 +++++++++++---------- weasyprint/formatting_structure/build.py | 13 +++++++------ weasyprint/html.py | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/weasyprint/formatting_structure/boxes.py b/weasyprint/formatting_structure/boxes.py index adab5772c..fa9590e5f 100644 --- a/weasyprint/formatting_structure/boxes.py +++ b/weasyprint/formatting_structure/boxes.py @@ -89,8 +89,9 @@ class Box(object): def all_children(self): return () - def __init__(self, element_tag, style): + def __init__(self, element_tag, style, element): self.element_tag = element_tag + self.element = element self.style = style def __repr__(self): @@ -101,7 +102,7 @@ def anonymous_from(cls, parent, *args, **kwargs): """Return an anonymous box that inherits from ``parent``.""" style = computed_from_cascaded( cascaded={}, parent_style=parent.style, element=None) - return cls(parent.element_tag, style, *args, **kwargs) + return cls(parent.element_tag, style, parent.element, *args, **kwargs) def copy(self): """Return shallow copy of the box.""" @@ -297,8 +298,8 @@ def page_values(self): class ParentBox(Box): """A box that has children.""" - def __init__(self, element_tag, style, children): - super(ParentBox, self).__init__(element_tag, style) + def __init__(self, element_tag, style, element, children): + super(ParentBox, self).__init__(element_tag, style, element) self.children = tuple(children) def all_children(self): @@ -482,9 +483,9 @@ class TextBox(InlineLevelBox): ascii_to_wide = dict((i, chr(i + 0xfee0)) for i in range(0x21, 0x7f)) ascii_to_wide.update({0x20: '\u3000', 0x2D: '\u2212'}) - def __init__(self, element_tag, style, text): + def __init__(self, element_tag, style, element, text): assert text - super(TextBox, self).__init__(element_tag, style) + super(TextBox, self).__init__(element_tag, style, element) text_transform = style['text_transform'] if text_transform != 'none': text = { @@ -532,8 +533,8 @@ class ReplacedBox(Box): and is opaque from CSS’s point of view. """ - def __init__(self, element_tag, style, replacement): - super(ReplacedBox, self).__init__(element_tag, style) + def __init__(self, element_tag, style, element, replacement): + super(ReplacedBox, self).__init__(element_tag, style, element) self.replacement = replacement @@ -683,7 +684,7 @@ def __init__(self, page_type, style): self.page_type = page_type # Page boxes are not linked to any element. super(PageBox, self).__init__( - element_tag=None, style=style, children=[]) + element_tag=None, style=style, element=None, children=[]) def __repr__(self): return '<%s %s>' % (type(self).__name__, self.page_type) @@ -695,7 +696,7 @@ def __init__(self, at_keyword, style): self.at_keyword = at_keyword # Margin boxes are not linked to any element. super(MarginBox, self).__init__( - element_tag=None, style=style, children=[]) + element_tag=None, style=style, element=None, children=[]) def __repr__(self): return '<%s %s>' % (type(self).__name__, self.at_keyword) diff --git a/weasyprint/formatting_structure/build.py b/weasyprint/formatting_structure/build.py index f0d6b0499..791c66b14 100644 --- a/weasyprint/formatting_structure/build.py +++ b/weasyprint/formatting_structure/build.py @@ -80,9 +80,10 @@ def root_style_for(element, pseudo_type=None): return box -def make_box(element_tag, style, content): - return BOX_TYPE_FROM_DISPLAY[style['display']]( - element_tag, style, content) +def make_box(element_tag, style, content, element): + box = BOX_TYPE_FROM_DISPLAY[style['display']]( + element_tag, style, element, content) + return box def element_to_box(element, style_for, get_image_from_uri, base_url, @@ -122,7 +123,7 @@ def element_to_box(element, style_for, get_image_from_uri, base_url, if display == 'none': return [] - box = make_box(element.tag, style, []) + box = make_box(element.tag, style, [], element) if state is None: # use a list to have a shared mutable object @@ -227,7 +228,7 @@ def before_after_to_box(element, pseudo_type, state, style_for, if 'none' in (display, content) or content in ('normal', 'inhibit'): return [] - box = make_box('%s::%s' % (element.tag, pseudo_type), style, []) + box = make_box('%s::%s' % (element.tag, pseudo_type), style, [], element) quote_depth, counter_values, _counter_scopes = state update_counters(state, style) @@ -264,7 +265,7 @@ def marker_to_box(element, state, parent_style, style_for, get_image_from_uri, # `content` where 'normal' computes as 'inhibit' for pseudo elements. quote_depth, counter_values, _counter_scopes = state - box = make_box('%s::marker' % element.tag, style, children) + box = make_box('%s::marker' % element.tag, style, children, element) if style['display'] == 'none': return diff --git a/weasyprint/html.py b/weasyprint/html.py index 76341a635..48e17f6f9 100644 --- a/weasyprint/html.py +++ b/weasyprint/html.py @@ -111,7 +111,7 @@ def make_replaced_box(element, box, image): else: # TODO: support images with 'display: table-cell'? type_ = boxes.InlineReplacedBox - new_box = type_(element.tag, box.style, image) + new_box = type_(element.tag, box.style, element, image) # TODO: check other attributes that need to be copied # TODO: find another solution new_box.string_set = box.string_set