Improve markdown support

main
Bob Mottram 2022-06-27 11:38:31 +01:00
parent bc083f4bbe
commit d3b1b5acda
3 changed files with 154 additions and 4 deletions

View File

@ -32,7 +32,13 @@ def _markdown_emphasis_html(markdown: str) -> str:
'_:': '</ul>:', '_:': '</ul>:',
'_;': '</ul>;', '_;': '</ul>;',
'_,': '</ul>,', '_,': '</ul>,',
'_\n': '</ul>\n' '_\n': '</ul>\n',
' `': '<em>',
'`.': '</em>',
'`:': '</em>',
'`;': '</em>',
'`\n': '</em>',
'` ': '</em>'
} }
for md_str, html in replacements.items(): for md_str, html in replacements.items():
markdown = markdown.replace(md_str, html) markdown = markdown.replace(md_str, html)
@ -61,7 +67,19 @@ def _markdown_replace_quotes(markdown: str) -> str:
lines = markdown.split('\n') lines = markdown.split('\n')
result = '' result = ''
prev_quote_line = None prev_quote_line = None
code_section = False
for line in lines: for line in lines:
# avoid code sections
if not code_section:
if '<code>' in line:
code_section = True
else:
if '</code>' in line:
code_section = False
if code_section:
result += line + '\n'
continue
if '> ' not in line: if '> ' not in line:
result += line + '\n' result += line + '\n'
prev_quote_line = None prev_quote_line = None
@ -128,9 +146,101 @@ def _markdown_replace_links(markdown: str, images: bool = False) -> str:
return markdown return markdown
def _markdown_replace_bullet_points(markdown: str) -> str:
"""Replaces bullet points
"""
lines = markdown.split('\n')
bullet_style = ('* ', ' * ', '- ', ' - ')
bullet_matched = ''
start_line = -1
line_ctr = 0
changed = False
code_section = False
for line in lines:
if not line.strip():
# skip blank lines
line_ctr += 1
continue
# skip over code sections
if not code_section:
if '<code>' in line:
code_section = True
else:
if '</code>' in line:
code_section = False
if code_section:
line_ctr += 1
continue
if not bullet_matched:
for test_str in bullet_style:
if line.startswith(test_str):
bullet_matched = test_str
start_line = line_ctr
break
else:
if not line.startswith(bullet_matched):
for index in range(start_line, line_ctr):
line_text = lines[index].replace(bullet_matched, '', 1)
if index == start_line:
lines[index] = '<ul>\n<li>' + line_text + '</li>'
elif index == line_ctr - 1:
lines[index] = '<li>' + line_text + '</li>\n</ul>'
else:
lines[index] = '<li>' + line_text + '</li>'
changed = True
start_line = -1
bullet_matched = ''
line_ctr += 1
if not changed:
return markdown
markdown = ''
for line in lines:
markdown += line + '\n'
return markdown
def _markdown_replace_code(markdown: str) -> str:
"""Replaces code sections within markdown
"""
lines = markdown.split('\n')
start_line = -1
line_ctr = 0
changed = False
section_active = False
for line in lines:
if not line.strip():
# skip blank lines
line_ctr += 1
continue
if line.startswith('```'):
if not section_active:
start_line = line_ctr
section_active = True
else:
lines[start_line] = '<code>'
lines[line_ctr] = '</code>'
section_active = False
changed = True
line_ctr += 1
if not changed:
return markdown
markdown = ''
for line in lines:
markdown += line + '\n'
return markdown
def markdown_to_html(markdown: str) -> str: def markdown_to_html(markdown: str) -> str:
"""Converts markdown formatted text to html """Converts markdown formatted text to html
""" """
markdown = _markdown_replace_code(markdown)
markdown = _markdown_replace_bullet_points(markdown)
markdown = _markdown_replace_quotes(markdown) markdown = _markdown_replace_quotes(markdown)
markdown = _markdown_emphasis_html(markdown) markdown = _markdown_emphasis_html(markdown)
markdown = _markdown_replace_links(markdown, True) markdown = _markdown_replace_links(markdown, True)
@ -140,6 +250,7 @@ def markdown_to_html(markdown: str) -> str:
lines_list = markdown.split('\n') lines_list = markdown.split('\n')
html_str = '' html_str = ''
ctr = 0 ctr = 0
code_section = False
titles = { titles = {
"h5": '#####', "h5": '#####',
"h4": '####', "h4": '####',
@ -150,6 +261,19 @@ def markdown_to_html(markdown: str) -> str:
for line in lines_list: for line in lines_list:
if ctr > 0: if ctr > 0:
html_str += '<br>' html_str += '<br>'
# avoid code sections
if not code_section:
if '<code>' in line:
code_section = True
else:
if '</code>' in line:
code_section = False
if code_section:
html_str += line
ctr += 1
continue
for hsh, hashes in titles.items(): for hsh, hashes in titles.items():
if line.startswith(hashes): if line.startswith(hashes):
line = line.replace(hashes, '').strip() line = line.replace(hashes, '').strip()

View File

@ -6,7 +6,7 @@ The ActivityPub protocol is a decentralized social networking protocol based upo
## Status of This Document ## Status of This Document
*This document is based upon the 2018 version of the []W3C ActivityPub specification](https://www.w3.org/TR/activitypub). Any alterations are for the purposes of more accurately reflecting the actual use of the protocol, with the aim of creating less confusion for new implementors.* *This document is based upon the 2018 version of the [W3C ActivityPub specification](https://www.w3.org/TR/activitypub). Any alterations are for the purposes of more accurately reflecting the actual use of the protocol, with the aim of creating less confusion for new implementors.*
# 1. Overview # 1. Overview
@ -19,8 +19,8 @@ ActivityPub implementations can implement just one of these things or both of th
In ActivityPub, a user is represented by "actors" via the user's accounts on servers. User's accounts on different servers correspond to different actors. Every Actor has: In ActivityPub, a user is represented by "actors" via the user's accounts on servers. User's accounts on different servers correspond to different actors. Every Actor has:
- **An `inbox`:** How they get messages from the world * **An `inbox`:** How they get messages from the world
- **An `outbox`:** How they send messages to others * **An `outbox`:** How they send messages to others
![An Actor with inbox and outbox](activitypub-tutorial-1.png) ![An Actor with inbox and outbox](activitypub-tutorial-1.png)

View File

@ -5725,6 +5725,32 @@ def _test_markdown_to_html():
'This is a multi-line quotation:<br>' + \ 'This is a multi-line quotation:<br>' + \
'<blockquote><i>The first line The second line</i></blockquote>' '<blockquote><i>The first line The second line</i></blockquote>'
markdown = 'This is a list of points:\n' + \
' * Point 1\n' + \
' * Point 2\n\n' + \
'And some other text.'
result = markdown_to_html(markdown)
expected = \
'This is a list of points:<br><ul><br><li>Point 1</li><br>' + \
'<li>Point 2</li><br><li></li><br></ul><br>And some other text.<br>'
if result != expected:
print(result)
assert result == expected
markdown = 'This is a code section:\n' + \
'``` json\n' + \
'10 PRINT "YOLO"\n' + \
'20 GOTO 10\n' + \
'```\n\n' + \
'And some other text.'
result = markdown_to_html(markdown)
expected = \
'This is a code section:<br><code><br>10 PRINT "YOLO"<br>' + \
'20 GOTO 10<br></code><br><br>And some other text.<br>'
if result != expected:
print(result)
assert result == expected
markdown = 'This is **bold**' markdown = 'This is **bold**'
assert markdown_to_html(markdown) == 'This is <b>bold</b>' assert markdown_to_html(markdown) == 'This is <b>bold</b>'