From d3b1b5acdaa0491d1486d3a72cafdf40d8e08f6f Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 27 Jun 2022 11:38:31 +0100 Subject: [PATCH] Improve markdown support --- markdown.py | 126 ++++++++++++++++++++++++++++++++++- specification/activitypub.md | 6 +- tests.py | 26 ++++++++ 3 files changed, 154 insertions(+), 4 deletions(-) diff --git a/markdown.py b/markdown.py index 6434962bd..b22920333 100644 --- a/markdown.py +++ b/markdown.py @@ -32,7 +32,13 @@ def _markdown_emphasis_html(markdown: str) -> str: '_:': ':', '_;': ';', '_,': ',', - '_\n': '\n' + '_\n': '\n', + ' `': '', + '`.': '', + '`:': '', + '`;': '', + '`\n': '', + '` ': '' } for md_str, html in replacements.items(): markdown = markdown.replace(md_str, html) @@ -61,7 +67,19 @@ def _markdown_replace_quotes(markdown: str) -> str: lines = markdown.split('\n') result = '' prev_quote_line = None + code_section = False for line in lines: + # avoid code sections + if not code_section: + if '' in line: + code_section = True + else: + if '' in line: + code_section = False + if code_section: + result += line + '\n' + continue + if '> ' not in line: result += line + '\n' prev_quote_line = None @@ -128,9 +146,101 @@ def _markdown_replace_links(markdown: str, images: bool = False) -> str: 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 '' in line: + code_section = True + else: + if '' 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] = '' + else: + lines[index] = '
  • ' + line_text + '
  • ' + 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] = '' + lines[line_ctr] = '' + 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: """Converts markdown formatted text to html """ + markdown = _markdown_replace_code(markdown) + markdown = _markdown_replace_bullet_points(markdown) markdown = _markdown_replace_quotes(markdown) markdown = _markdown_emphasis_html(markdown) markdown = _markdown_replace_links(markdown, True) @@ -140,6 +250,7 @@ def markdown_to_html(markdown: str) -> str: lines_list = markdown.split('\n') html_str = '' ctr = 0 + code_section = False titles = { "h5": '#####', "h4": '####', @@ -150,6 +261,19 @@ def markdown_to_html(markdown: str) -> str: for line in lines_list: if ctr > 0: html_str += '
    ' + + # avoid code sections + if not code_section: + if '' in line: + code_section = True + else: + if '' in line: + code_section = False + if code_section: + html_str += line + ctr += 1 + continue + for hsh, hashes in titles.items(): if line.startswith(hashes): line = line.replace(hashes, '').strip() diff --git a/specification/activitypub.md b/specification/activitypub.md index 13292eaf0..04597ec76 100644 --- a/specification/activitypub.md +++ b/specification/activitypub.md @@ -6,7 +6,7 @@ The ActivityPub protocol is a decentralized social networking protocol based upo ## 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 @@ -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: -- **An `inbox`:** How they get messages from the world -- **An `outbox`:** How they send messages to others + * **An `inbox`:** How they get messages from the world + * **An `outbox`:** How they send messages to others ![An Actor with inbox and outbox](activitypub-tutorial-1.png) diff --git a/tests.py b/tests.py index 31f7b0746..cf71f0806 100644 --- a/tests.py +++ b/tests.py @@ -5725,6 +5725,32 @@ def _test_markdown_to_html(): 'This is a multi-line quotation:
    ' + \ '
    The first line The second line
    ' + 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:

    And some other text.
    ' + 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:

    10 PRINT "YOLO"
    ' + \ + '20 GOTO 10


    And some other text.
    ' + if result != expected: + print(result) + assert result == expected + markdown = 'This is **bold**' assert markdown_to_html(markdown) == 'This is bold'