diff --git a/markdownify/__init__.py b/markdownify/__init__.py
index cd66a39..efb2d15 100644
--- a/markdownify/__init__.py
+++ b/markdownify/__init__.py
@@ -148,7 +148,13 @@ def is_nested_node(el):
elif isinstance(el, NavigableString):
text += self.process_text(el)
else:
- text += self.process_tag(el, convert_children_as_inline)
+ text_strip = text.rstrip('\n')
+ newlines_left = len(text) - len(text_strip)
+ next_text = self.process_tag(el, convert_children_as_inline)
+ next_text_strip = next_text.lstrip('\n')
+ newlines_right = len(next_text) - len(next_text_strip)
+ newlines = '\n' * max(newlines_left, newlines_right)
+ text = text_strip + newlines + next_text_strip
if not children_only:
convert_fn = getattr(self, 'convert_%s' % node.name, None)
@@ -221,7 +227,7 @@ def indent(self, text, level):
def underline(self, text, pad_char):
text = (text or '').rstrip()
- return '%s\n%s\n\n' % (text, pad_char * len(text)) if text else ''
+ return '\n\n%s\n%s\n\n' % (text, pad_char * len(text)) if text else ''
def convert_a(self, el, text, convert_as_inline):
prefix, suffix, text = chomp(text)
@@ -282,8 +288,8 @@ def convert_hn(self, n, el, text, convert_as_inline):
return self.underline(text, line)
hashes = '#' * n
if style == ATX_CLOSED:
- return '%s %s %s\n\n' % (hashes, text, hashes)
- return '%s %s\n\n' % (hashes, text)
+ return '\n%s %s %s\n\n' % (hashes, text, hashes)
+ return '\n%s %s\n\n' % (hashes, text)
def convert_hr(self, el, text, convert_as_inline):
return '\n\n---\n\n'
@@ -318,7 +324,7 @@ def convert_list(self, el, text, convert_as_inline):
if nested:
# remove trailing newline if nested
return '\n' + self.indent(text, 1).rstrip()
- return text + ('\n' if before_paragraph else '')
+ return '\n\n' + text + ('\n' if before_paragraph else '')
convert_ul = convert_list
convert_ol = convert_list
@@ -349,7 +355,7 @@ def convert_p(self, el, text, convert_as_inline):
width=self.options['wrap_width'],
break_long_words=False,
break_on_hyphens=False)
- return '%s\n\n' % text if text else ''
+ return '\n\n%s\n\n' % text if text else ''
def convert_pre(self, el, text, convert_as_inline):
if not text:
diff --git a/tests/test_advanced.py b/tests/test_advanced.py
index 14bf3cd..a3a5fda 100644
--- a/tests/test_advanced.py
+++ b/tests/test_advanced.py
@@ -14,7 +14,7 @@ def test_chomp():
def test_nested():
text = md('
This is an example link.
')
- assert text == 'This is an [example link](http://example.com/).\n\n'
+ assert text == '\n\nThis is an [example link](http://example.com/).\n\n'
def test_ignore_comments():
diff --git a/tests/test_conversions.py b/tests/test_conversions.py
index a35b982..baa294b 100644
--- a/tests/test_conversions.py
+++ b/tests/test_conversions.py
@@ -112,36 +112,38 @@ def test_em():
def test_header_with_space():
- assert md('\n\nHello
') == '### Hello\n\n'
- assert md('\n\nHello
') == '#### Hello\n\n'
- assert md('\n\nHello
') == '##### Hello\n\n'
- assert md('\n\nHello\n\n
') == '##### Hello\n\n'
- assert md('\n\nHello \n\n
') == '##### Hello\n\n'
+ assert md('\n\nHello
') == '\n### Hello\n\n'
+ assert md('\n\nHello
') == '\n#### Hello\n\n'
+ assert md('\n\nHello
') == '\n##### Hello\n\n'
+ assert md('\n\nHello\n\n
') == '\n##### Hello\n\n'
+ assert md('\n\nHello \n\n
') == '\n##### Hello\n\n'
def test_h1():
- assert md('Hello
') == 'Hello\n=====\n\n'
+ assert md('Hello
') == '\n\nHello\n=====\n\n'
def test_h2():
- assert md('Hello
') == 'Hello\n-----\n\n'
+ assert md('Hello
') == '\n\nHello\n-----\n\n'
def test_hn():
- assert md('Hello
') == '### Hello\n\n'
- assert md('Hello
') == '#### Hello\n\n'
- assert md('Hello
') == '##### Hello\n\n'
- assert md('Hello
') == '###### Hello\n\n'
+ assert md('Hello
') == '\n### Hello\n\n'
+ assert md('Hello
') == '\n#### Hello\n\n'
+ assert md('Hello
') == '\n##### Hello\n\n'
+ assert md('Hello
') == '\n###### Hello\n\n'
def test_hn_chained():
- assert md('First
\nSecond
\nThird
', heading_style=ATX) == '# First\n\n\n## Second\n\n\n### Third\n\n'
- assert md('XFirst
', heading_style=ATX) == 'X# First\n\n'
+ assert md('First
\nSecond
\nThird
', heading_style=ATX) == '\n# First\n\n\n## Second\n\n\n### Third\n\n'
+ assert md('XFirst
', heading_style=ATX) == 'X\n# First\n\n'
+ assert md('XFirst
', heading_style=ATX_CLOSED) == 'X\n# First #\n\n'
+ assert md('XFirst
') == 'X\n\nFirst\n=====\n\n'
def test_hn_nested_tag_heading_style():
- assert md('A
P
C ', heading_style=ATX_CLOSED) == '# A P C #\n\n'
- assert md('A
P
C ', heading_style=ATX) == '# A P C\n\n'
+ assert md('A
P
C ', heading_style=ATX_CLOSED) == '\n# A P C #\n\n'
+ assert md('A
P
C ', heading_style=ATX) == '\n# A P C\n\n'
def test_hn_nested_simple_tag():
@@ -157,12 +159,12 @@ def test_hn_nested_simple_tag():
]
for tag, markdown in tag_to_markdown:
- assert md('A <' + tag + '>' + tag + '' + tag + '> B
') == '### A ' + markdown + ' B\n\n'
+ assert md('A <' + tag + '>' + tag + '' + tag + '> B
') == '\n### A ' + markdown + ' B\n\n'
- assert md('A
B
', heading_style=ATX) == '### A B\n\n'
+ assert md('A
B
', heading_style=ATX) == '\n### A B\n\n'
# Nested lists not supported
- # assert md('A
', heading_style=ATX) == '### A li1 li2 B\n\n'
+ # assert md('A
', heading_style=ATX) == '\n### A li1 li2 B\n\n'
def test_hn_nested_img():
@@ -172,18 +174,18 @@ def test_hn_nested_img():
("alt='Alt Text' title='Optional title'", "Alt Text", " \"Optional title\""),
]
for image_attributes, markdown, title in image_attributes_to_markdown:
- assert md('A
B
') == '### A ' + markdown + ' B\n\n'
- assert md('A
B
', keep_inline_images_in=['h3']) == '### A  B\n\n'
+ assert md('A
B
') == '\n### A ' + markdown + ' B\n\n'
+ assert md('A
B
', keep_inline_images_in=['h3']) == '\n### A  B\n\n'
def test_hn_atx_headings():
- assert md('Hello
', heading_style=ATX) == '# Hello\n\n'
- assert md('Hello
', heading_style=ATX) == '## Hello\n\n'
+ assert md('Hello
', heading_style=ATX) == '\n# Hello\n\n'
+ assert md('Hello
', heading_style=ATX) == '\n## Hello\n\n'
def test_hn_atx_closed_headings():
- assert md('Hello
', heading_style=ATX_CLOSED) == '# Hello #\n\n'
- assert md('Hello
', heading_style=ATX_CLOSED) == '## Hello ##\n\n'
+ assert md('Hello
', heading_style=ATX_CLOSED) == '\n# Hello #\n\n'
+ assert md('Hello
', heading_style=ATX_CLOSED) == '\n## Hello ##\n\n'
def test_head():
@@ -193,7 +195,7 @@ def test_head():
def test_hr():
assert md('Hello
World') == 'Hello\n\n---\n\nWorld'
assert md('Hello
World') == 'Hello\n\n---\n\nWorld'
- assert md('Hello
\n
\nWorld
') == 'Hello\n\n\n\n\n---\n\n\nWorld\n\n'
+ assert md('Hello
\n
\nWorld
') == '\n\nHello\n\n\n---\n\n\nWorld\n\n'
def test_i():
@@ -210,12 +212,13 @@ def test_kbd():
def test_p():
- assert md('hello
') == 'hello\n\n'
- assert md('123456789 123456789
') == '123456789 123456789\n\n'
- assert md('123456789 123456789
', wrap=True, wrap_width=10) == '123456789\n123456789\n\n'
- assert md('Some long link
', wrap=True, wrap_width=10) == '[Some long\nlink](https://example.com)\n\n'
- assert md('12345
67890
', wrap=True, wrap_width=10, newline_style=BACKSLASH) == '12345\\\n67890\n\n'
- assert md('12345678901
12345
', wrap=True, wrap_width=10, newline_style=BACKSLASH) == '12345678901\\\n12345\n\n'
+ assert md('hello
') == '\n\nhello\n\n'
+ assert md('123456789 123456789
') == '\n\n123456789 123456789\n\n'
+ assert md('123456789 123456789
', wrap=True, wrap_width=10) == '\n\n123456789\n123456789\n\n'
+ assert md('Some long link
', wrap=True, wrap_width=10) == '\n\n[Some long\nlink](https://example.com)\n\n'
+ assert md('12345
67890
', wrap=True, wrap_width=10, newline_style=BACKSLASH) == '\n\n12345\\\n67890\n\n'
+ assert md('12345678901
12345
', wrap=True, wrap_width=10, newline_style=BACKSLASH) == '\n\n12345678901\\\n12345\n\n'
+ assert md('FirstSecond
Third
Fourth') == 'First\n\nSecond\n\nThird\n\nFourth'
def test_pre():
diff --git a/tests/test_lists.py b/tests/test_lists.py
index 35eee13..ecc1a65 100644
--- a/tests/test_lists.py
+++ b/tests/test_lists.py
@@ -41,19 +41,20 @@
def test_ol():
- assert md('- a
- b
') == '1. a\n2. b\n'
- assert md('- a
- b
') == '3. a\n4. b\n'
- assert md('- a
- b
') == '1. a\n2. b\n'
- assert md('- a
- b
') == '1. a\n2. b\n'
- assert md('- a
- b
') == '1. a\n2. b\n'
+ assert md('- a
- b
') == '\n\n1. a\n2. b\n'
+ assert md('- a
- b
') == '\n\n3. a\n4. b\n'
+ assert md('foo- a
- b
bar') == 'foo\n\n3. a\n4. b\n\nbar'
+ assert md('- a
- b
') == '\n\n1. a\n2. b\n'
+ assert md('- a
- b
') == '\n\n1. a\n2. b\n'
+ assert md('- a
- b
') == '\n\n1. a\n2. b\n'
def test_nested_ols():
- assert md(nested_ols) == '\n1. 1\n\t1. a\n\t\t1. I\n\t\t2. II\n\t\t3. III\n\t2. b\n\t3. c\n2. 2\n3. 3\n'
+ assert md(nested_ols) == '\n\n1. 1\n\t1. a\n\t\t1. I\n\t\t2. II\n\t\t3. III\n\t2. b\n\t3. c\n2. 2\n3. 3\n'
def test_ul():
- assert md('') == '* a\n* b\n'
+ assert md('') == '\n\n* a\n* b\n'
assert md("""
-
a
@@ -61,11 +62,12 @@ def test_ul():
- b
- c
-
""") == '* a\n* b\n* c\n'
+ """) == '\n\n* a\n* b\n* c\n'
def test_inline_ul():
- assert md('foo
bar
') == 'foo\n\n* a\n* b\n\nbar\n\n'
+ assert md('foo
bar
') == '\n\nfoo\n\n* a\n* b\n\nbar\n\n'
+ assert md('foobaz') == 'foo\n\n* bar\n\nbaz'
def test_nested_uls():
@@ -73,12 +75,12 @@ def test_nested_uls():
Nested ULs should alternate bullet characters.
"""
- assert md(nested_uls) == '\n* 1\n\t+ a\n\t\t- I\n\t\t- II\n\t\t- III\n\t+ b\n\t+ c\n* 2\n* 3\n'
+ assert md(nested_uls) == '\n\n* 1\n\t+ a\n\t\t- I\n\t\t- II\n\t\t- III\n\t+ b\n\t+ c\n* 2\n* 3\n'
def test_bullets():
- assert md(nested_uls, bullets='-') == '\n- 1\n\t- a\n\t\t- I\n\t\t- II\n\t\t- III\n\t- b\n\t- c\n- 2\n- 3\n'
+ assert md(nested_uls, bullets='-') == '\n\n- 1\n\t- a\n\t\t- I\n\t\t- II\n\t\t- III\n\t- b\n\t- c\n- 2\n- 3\n'
def test_li_text():
- assert md('- foo bar
- foo bar
- foo bar space.
') == '* foo [bar](#)\n* foo bar\n* foo **bar** *space*.\n'
+ assert md('- foo bar
- foo bar
- foo bar space.
') == '\n\n* foo [bar](#)\n* foo bar\n* foo **bar** *space*.\n'