aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2015-02-08 21:26:24 +0000
committerMichael Williamson <mike@zwobble.org>2015-02-08 21:26:24 +0000
commit1175173c0d8f6787bf6b789b8e5f6e4cd0040411 (patch)
tree0d5c5a4e57939cb54c62e94e07cc2043a89f515a
parent0d4206bdf8791be7d7488d8720b6146d187f433f (diff)
Handle nested lists in markdown writer
-rw-r--r--mammoth/writers/markdown.py66
-rw-r--r--tests/writers/markdown_tests.py24
2 files changed, 74 insertions, 16 deletions
diff --git a/mammoth/writers/markdown.py b/mammoth/writers/markdown.py
index 948e197..9424d45 100644
--- a/mammoth/writers/markdown.py
+++ b/mammoth/writers/markdown.py
@@ -4,25 +4,35 @@ import re
class _WriterOutput(object):
- def __init__(self, start, end, anchor_position=None, markdown_state=None):
+ def __init__(self, start, end, anchor_position=None):
+ if not callable(end):
+ end_output = end
+ end = lambda: end_output
+
self.start = start
self.end = end
self.anchor_position = anchor_position
- self.markdown_state = markdown_state
class _MarkdownState(object):
- def __init__(self, list_state=None):
+ def __init__(self):
+ self._list_state_stack = []
+ self.list_state = None
+ self.list_item_has_closed = False
+
+ def update_list_state(self, list_state):
+ self._list_state_stack.append(self.list_state)
self.list_state = list_state
- def updated_list_state(self, list_state):
- return _MarkdownState(list_state)
+ def pop_list_state(self):
+ self.list_state = self._list_state_stack.pop()
class _MarkdownListState(object):
- def __init__(self, ordered):
+ def __init__(self, ordered, indentation):
self.ordered = ordered
self.count = 0
+ self.indentation = indentation
def _symmetric_wrapped(end):
@@ -60,15 +70,33 @@ def _image(attributes, markdown_state):
def _list(ordered):
def call(attributes, markdown_state):
- list_state = _MarkdownListState(ordered=ordered)
- markdown_state = markdown_state.updated_list_state(list_state)
- return _WriterOutput("", "\n", markdown_state=markdown_state)
+ if markdown_state.list_state is None:
+ start = ""
+ end_text = "\n"
+ indentation = 0
+ else:
+ start = "\n"
+ end_text = ""
+ indentation = markdown_state.list_state.indentation + 1
+
+ def end():
+ markdown_state.pop_list_state()
+ return end_text
+
+ markdown_state.update_list_state(_MarkdownListState(
+ ordered=ordered,
+ indentation=indentation,
+ ))
+
+ return _WriterOutput(start, end)
return call
def _list_item(attributes, markdown_state):
- list_state = markdown_state.list_state or _MarkdownListState(ordered=False)
+ markdown_state.list_item_has_closed = False
+
+ list_state = markdown_state.list_state or _MarkdownListState(ordered=False, indentation=0)
list_state.count += 1
if list_state.ordered:
@@ -76,7 +104,14 @@ def _list_item(attributes, markdown_state):
else:
bullet = "-"
- return _WriterOutput(bullet + " ", "\n")
+ def end():
+ if markdown_state.list_item_has_closed:
+ return ""
+ else:
+ markdown_state.list_item_has_closed = True
+ return "\n"
+
+ return _WriterOutput(("\t" * list_state.indentation) + bullet + " ", end)
def _init_writers():
@@ -117,9 +152,7 @@ class MarkdownWriter(object):
attributes = {}
output = _writers.get(name, _default_writer)(attributes, self._markdown_state)
- self._element_stack.append((output.end, self._markdown_state))
- if output.markdown_state is not None:
- self._markdown_state = output.markdown_state
+ self._element_stack.append(output.end)
anchor_before_start = output.anchor_position == "before"
if anchor_before_start:
@@ -133,8 +166,9 @@ class MarkdownWriter(object):
def end(self, name):
- end, markdown_state = self._element_stack.pop()
- self._fragments.append(end)
+ end = self._element_stack.pop()
+ output = end()
+ self._fragments.append(output)
def self_closing(self, name, attributes=None):
self.start(name, attributes)
diff --git a/tests/writers/markdown_tests.py b/tests/writers/markdown_tests.py
index 05db8ff..27d6d56 100644
--- a/tests/writers/markdown_tests.py
+++ b/tests/writers/markdown_tests.py
@@ -175,6 +175,30 @@ def ul_element_is_written_as_unordered_list_using_hyphens_as_bullets():
writer.end("li")
writer.end("ul")
assert_equal("- Fruit\n- Condiments\n\n", writer.as_string())
+
+
+@istest
+def numbering_is_separate_for_nested_list_and_parent_list():
+ writer = _create_writer()
+ writer.start("ol")
+
+ writer.start("li")
+ writer.text("Fruit")
+ writer.start("ol")
+ writer.start("li")
+ writer.text("Apple")
+ writer.end("li")
+ writer.start("li")
+ writer.text("Banana")
+ writer.end("li")
+ writer.end("ol")
+ writer.end("li")
+
+ writer.start("li")
+ writer.text("Condiments")
+ writer.end("li")
+ writer.end("ol")
+ assert_equal("1. Fruit\n\t1. Apple\n\t2. Banana\n2. Condiments\n\n", writer.as_string())