aboutsummaryrefslogtreecommitdiff
path: root/mammoth/html
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2016-03-14 18:56:42 +0000
committerMichael Williamson <mike@zwobble.org>2016-03-14 20:09:13 +0000
commitb34f7280c0754f9fc88725358e22ac46d9a2a598 (patch)
tree350a5563a0cd06bb8c97e932f7f275edc4106705 /mammoth/html
parent8f3486e5fc69f2402476b830d21b271a93ed0046 (diff)
Add collapsing of HTML nodes
Diffstat (limited to 'mammoth/html')
-rw-r--r--mammoth/html/__init__.py68
-rw-r--r--mammoth/html/nodes.py4
2 files changed, 70 insertions, 2 deletions
diff --git a/mammoth/html/__init__.py b/mammoth/html/__init__.py
index 905b423..54bb87d 100644
--- a/mammoth/html/__init__.py
+++ b/mammoth/html/__init__.py
@@ -7,13 +7,22 @@ def text(value):
def element(tag_name, attributes=None, children=None):
+ return _element(tag_name, attributes, children, collapsible=False)
+
+
+def collapsible_element(tag_name, attributes=None, children=None):
+ return _element(tag_name, attributes, children, collapsible=True)
+
+
+def _element(tag_names, attributes, children, collapsible):
+ if not isinstance(tag_names, list):
+ tag_names = [tag_names]
if attributes is None:
attributes = {}
if children is None:
children = []
+ return Element(tag_names, attributes, children, collapsible=collapsible)
- return Element([tag_name], attributes, children, collapsible=False)
-
def self_closing_element(tag_name, attributes=None):
if attributes is None:
@@ -56,3 +65,58 @@ class StripEmpty(NodeVisitor):
def visit_force_write(self, node):
return [node]
+
+
+def collapse(nodes):
+ collapsed = []
+
+ for node in nodes:
+ _collapsing_add(collapsed, node)
+
+ return collapsed
+
+class _CollapseNode(NodeVisitor):
+ def visit_text_node(self, node):
+ return node
+
+ def visit_element(self, element):
+ return Element(
+ element.tag_names,
+ element.attributes,
+ collapse(element.children),
+ collapsible=element.collapsible)
+
+ def visit_self_closing_element(self, element):
+ return element
+
+ def visit_force_write(self, node):
+ return node
+
+_collapse_node = _CollapseNode().visit
+
+
+def _collapsing_add(collapsed, node):
+ collapsed_node = _collapse_node(node)
+ if not _try_collapse(collapsed, collapsed_node):
+ collapsed.append(collapsed_node)
+
+def _try_collapse(collapsed, node):
+ if not collapsed:
+ return False
+
+ last = collapsed[-1]
+ if not isinstance(last, Element) or not isinstance(node, Element):
+ return False
+
+ if not node.collapsible:
+ return False
+
+ if not _is_match(last, node):
+ return False
+
+ for child in node.children:
+ _collapsing_add(last.children, child)
+ return True
+
+def _is_match(first, second):
+ return first.tag_name in second.tag_names and first.attributes == second.attributes
diff --git a/mammoth/html/nodes.py b/mammoth/html/nodes.py
index aae4888..a5a5bde 100644
--- a/mammoth/html/nodes.py
+++ b/mammoth/html/nodes.py
@@ -16,6 +16,10 @@ class Element(Node):
attributes = cobble.field()
children = cobble.field()
collapsible = cobble.field()
+
+ @property
+ def tag_name(self):
+ return self.tag_names[0]
@cobble.data