aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2017-11-23 19:54:53 +0000
committerMichael Williamson <mike@zwobble.org>2017-11-23 19:54:53 +0000
commitc6e6a2b462d0bc5b7a5ac61d26c907e66cbcc946 (patch)
tree0ba9641dea203413923a08b44a8e7f56a5ee99f4
parentd44b2df9238e007cfe7bf1becf11b30e1e97d284 (diff)
Parse paragraph indents
-rw-r--r--mammoth/documents.py28
-rw-r--r--mammoth/docx/body_xml.py10
-rw-r--r--tests/docx/body_xml_tests.py55
3 files changed, 90 insertions, 3 deletions
diff --git a/mammoth/documents.py b/mammoth/documents.py
index e4372ab..b00f1bb 100644
--- a/mammoth/documents.py
+++ b/mammoth/documents.py
@@ -21,6 +21,24 @@ class Paragraph(HasChildren):
style_name = cobble.field()
numbering = cobble.field()
alignment = cobble.field()
+ indent = cobble.field()
+
+
+@cobble.data
+class ParagraphIndent(object):
+ start = cobble.field()
+ end = cobble.field()
+ first_line = cobble.field()
+ hanging = cobble.field()
+
+
+@cobble.data
+class Indent(object):
+ left = cobble.field()
+ right = cobble.field()
+ first_line = cobble.field()
+ hanging = cobble.field()
+
@cobble.data
class Run(HasChildren):
@@ -86,8 +104,14 @@ def document(children, notes=None, comments=None):
comments = []
return Document(children, notes, comments=comments)
-def paragraph(children, style_id=None, style_name=None, numbering=None, alignment=None):
- return Paragraph(children, style_id, style_name, numbering, alignment=alignment)
+def paragraph(children, style_id=None, style_name=None, numbering=None, alignment=None, indent=None):
+ if indent is None:
+ indent = paragraph_indent()
+
+ return Paragraph(children, style_id, style_name, numbering, alignment=alignment, indent=indent)
+
+def paragraph_indent(start=None, end=None, first_line=None, hanging=None):
+ return ParagraphIndent(start=start, end=end, first_line=first_line, hanging=hanging)
def run(
children,
diff --git a/mammoth/docx/body_xml.py b/mammoth/docx/body_xml.py
index 01920f0..cfe3493 100644
--- a/mammoth/docx/body_xml.py
+++ b/mammoth/docx/body_xml.py
@@ -120,6 +120,7 @@ def _create_reader(numbering, content_types, relationships, styles, docx_file, f
properties = element.find_child_or_null("w:pPr")
alignment = properties.find_child_or_null("w:jc").attributes.get("w:val")
numbering = _read_numbering_properties(properties.find_child_or_null("w:numPr"))
+ indent = _read_paragraph_indent(properties.find_child_or_null("w:ind"))
return _ReadResult.map_results(
_read_paragraph_style(properties),
@@ -130,6 +131,7 @@ def _create_reader(numbering, content_types, relationships, styles, docx_file, f
style_name=style[1],
numbering=numbering,
alignment=alignment,
+ indent=indent,
)).append_extra()
def _read_paragraph_style(properties):
@@ -203,6 +205,14 @@ def _create_reader(numbering, content_types, relationships, styles, docx_file, f
else:
return numbering.find_level(num_id, level_index)
+ def _read_paragraph_indent(element):
+ attributes = element.attributes
+ return documents.paragraph_indent(
+ start=attributes.get("w:start") or attributes.get("w:left"),
+ end=attributes.get("w:end") or attributes.get("w:right"),
+ first_line=attributes.get("w:firstLine"),
+ hanging=attributes.get("w:hanging"),
+ )
def tab(element):
return _success(documents.tab())
diff --git a/tests/docx/body_xml_tests.py b/tests/docx/body_xml_tests.py
index d1dd071..067037e 100644
--- a/tests/docx/body_xml_tests.py
+++ b/tests/docx/body_xml_tests.py
@@ -97,7 +97,7 @@ class ParagraphTests(object):
paragraph_xml = xml_element("w:p", {}, [properties_xml])
paragraph = _read_and_get_document_xml_element(paragraph_xml)
assert_equal("center", paragraph.alignment)
-
+
@istest
def paragraph_has_no_numbering_if_it_has_no_numbering_properties(self):
element = xml_element("w:p")
@@ -145,6 +145,59 @@ class ParagraphTests(object):
@istest
+class ParagraphIndentTests(object):
+ @istest
+ def when_w_start_is_set_then_start_indent_is_read_from_w_start(self):
+ paragraph_xml = self._paragraph_with_indent({"w:start": "720", "w:left": "40"})
+ paragraph = _read_and_get_document_xml_element(paragraph_xml)
+ assert_equal("720", paragraph.indent.start)
+
+ @istest
+ def when_w_start_is_not_set_then_start_indent_is_read_from_w_left(self):
+ paragraph_xml = self._paragraph_with_indent({"w:left": "720"})
+ paragraph = _read_and_get_document_xml_element(paragraph_xml)
+ assert_equal("720", paragraph.indent.start)
+
+ @istest
+ def when_w_end_is_set_then_end_indent_is_read_from_w_end(self):
+ paragraph_xml = self._paragraph_with_indent({"w:end": "720", "w:right": "40"})
+ paragraph = _read_and_get_document_xml_element(paragraph_xml)
+ assert_equal("720", paragraph.indent.end)
+
+ @istest
+ def when_w_end_is_not_set_then_end_indent_is_read_from_w_right(self):
+ paragraph_xml = self._paragraph_with_indent({"w:right": "720"})
+ paragraph = _read_and_get_document_xml_element(paragraph_xml)
+ assert_equal("720", paragraph.indent.end)
+
+ @istest
+ def paragraph_has_indent_first_line_read_from_paragraph_properties_if_present(self):
+ paragraph_xml = self._paragraph_with_indent({"w:firstLine": "720"})
+ paragraph = _read_and_get_document_xml_element(paragraph_xml)
+ assert_equal("720", paragraph.indent.first_line)
+
+ @istest
+ def paragraph_has_indent_hanging_read_from_paragraph_properties_if_present(self):
+ paragraph_xml = self._paragraph_with_indent({"w:hanging": "720"})
+ paragraph = _read_and_get_document_xml_element(paragraph_xml)
+ assert_equal("720", paragraph.indent.hanging)
+
+ @istest
+ def when_indent_attributes_arent_set_then_indents_are_none(self):
+ paragraph_xml = self._paragraph_with_indent({})
+ paragraph = _read_and_get_document_xml_element(paragraph_xml)
+ assert_equal(None, paragraph.indent.start)
+ assert_equal(None, paragraph.indent.end)
+ assert_equal(None, paragraph.indent.first_line)
+ assert_equal(None, paragraph.indent.hanging)
+
+ def _paragraph_with_indent(self, attributes):
+ indent_xml = xml_element("w:ind", attributes)
+ properties_xml = xml_element("w:pPr", {}, [indent_xml])
+ return xml_element("w:p", {}, [properties_xml])
+
+
+@istest
class RunTests(object):
@istest
def run_has_no_style_if_it_has_no_properties(self):