mirror of https://gitlab.com/bashrc2/epicyon
Improve markdown support
parent
bc083f4bbe
commit
d3b1b5acda
126
markdown.py
126
markdown.py
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
26
tests.py
26
tests.py
|
@ -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>'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue