Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Better handling of one-liner Block HTML
Fixes #1074
  • Loading branch information
facelessuser committed Jan 25, 2025
commit 08a4137b5e1fea01b07d6872f6e3a69f3512938c
5 changes: 3 additions & 2 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed

* Backslash Unescape IDs set via `attr_list` on `toc` (#1493).
* `md_in_html` should now process content inside "markdown" blocks a similar way
* `md_in_html` will process content inside "markdown" blocks a similar way
as they are parsed outside of "markdown" blocks giving a more consistent
expectation to external extensions (#1503).
* `md_in_html` should not handle tags within inline code blocks better (#1075).
* `md_in_html` handle tags within inline code blocks better (#1075).
* `md_in_html` fix handling of one-liner block HTML handling (#1074)

## [3.7] -- 2024-08-16

Expand Down
20 changes: 20 additions & 0 deletions markdown/extensions/md_in_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def reset(self):
self.mdstack: list[str] = [] # When markdown=1, stack contains a list of tags
self.treebuilder = etree.TreeBuilder()
self.mdstate: list[Literal['block', 'span', 'off', None]] = []
self.mdstarted: list[bool] = []
super().reset()

def close(self):
Expand Down Expand Up @@ -126,8 +127,24 @@ def handle_starttag(self, tag, attrs):
self.handle_endtag('p')
self.mdstate.append(state)
self.mdstack.append(tag)
self.mdstarted.append(True)
attrs['markdown'] = state
self.treebuilder.start(tag, attrs)

elif not self.inraw and tag in self.block_level_tags and self.mdstarted and self.mdstarted[-1]:
# Nested one-liner block tags `<tag><tag>...`
attrs = {key: value if value is not None else key for key, value in attrs}
state = self.get_state(tag, attrs)
if 'p' in self.mdstack and tag in self.block_level_tags:
# Close unclosed 'p' tag
self.handle_endtag('p')
self.mdstate.append(state)
self.mdstack.append(tag)
self.mdstarted.append(True)
attrs['markdown'] = state
self.treebuilder.start(tag, attrs)
return

else:
# Span level tag
if self.inraw:
Expand All @@ -151,6 +168,7 @@ def handle_endtag(self, tag):
while self.mdstack:
item = self.mdstack.pop()
self.mdstate.pop()
self.mdstarted.pop()
self.treebuilder.end(item)
if item == tag:
break
Expand Down Expand Up @@ -247,6 +265,8 @@ def handle_data(self, data):
if self.inraw or not self.mdstack:
super().handle_data(data)
else:
for i in range(len(self.mdstarted)):
self.mdstarted[i] = False
self.treebuilder.data(data)

def handle_empty_tag(self, data, is_block):
Expand Down
101 changes: 101 additions & 0 deletions tests/test_syntax/extensions/test_md_in_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -1274,6 +1274,107 @@ def test_md1_code_void_tag_multiline(self):
extensions=['md_in_html']
)

def test_md1_oneliner_block(self):
self.assertMarkdownRenders(
self.dedent(
'<div class="outer" markdown="block"><div class="inner" markdown="block">*foo*</div></div>'
),
'<div class="outer">\n'
'<div class="inner">\n'
'<p><em>foo</em></p>\n'
'</div>\n'
'</div>',
extensions=['md_in_html']
)

def test_md1_oneliner_block_mixed(self):
self.assertMarkdownRenders(
self.dedent(
"""
<div class="a" markdown="block"><div class="b" markdown="block">

<div class="c" markdown="block"><div class="d" markdown="block">
*foo*
</div></div>

</div></div>
"""
),
'<div class="a">\n'
'<div class="b">\n'
'<div class="c">\n'
'<div class="d">\n'
'<p><em>foo</em></p>\n'
'</div>\n'
'</div>\n'
'</div>\n'
'</div>',
extensions=['md_in_html']
)

def test_md1_oneliner_block_start(self):
self.assertMarkdownRenders(
self.dedent(
"""
<div class="outer" markdown="block"><div class="inner" markdown="block">
*foo*
</div></div>
"""
),
'<div class="outer">\n'
'<div class="inner">\n'
'<p><em>foo</em></p>\n'
'</div>\n'
'</div>',
extensions=['md_in_html']
)

def test_md1_oneliner_block_span(self):
self.assertMarkdownRenders(
self.dedent(
'<div class="outer" markdown="block"><div class="inner" markdown="span">*foo*</div></div>'
),
'<div class="outer">\n'
'<div class="inner"><em>foo</em></div>\n'
'</div>',
extensions=['md_in_html']
)

def test_md1_oneliner_block_span_start(self):
self.assertMarkdownRenders(
self.dedent(
"""
<div class="outer" markdown="block"><div class="inner" markdown="span">
*foo*
</div></div>
"""
),
'<div class="outer">\n'
'<div class="inner">\n'
'<em>foo</em>\n'
'</div>\n'
'</div>',
extensions=['md_in_html']
)

def test_md1_oneliner_span_block_start(self):
self.assertMarkdownRenders(
self.dedent(
"""
<div class="outer" markdown="span"><div class="inner" markdown="block">
*foo*
</div>
*foo*
</div>
"""
),
'<div class="outer">\n'
'<div class="inner">\n'
'<em>foo</em>\n'
'</div>\n\n'
'<em>foo</em></div>',
extensions=['md_in_html']
)

def test_md1_code_comment(self):

Expand Down