Move markdown functions to a separate module

main
Bob Mottram 2021-06-25 15:38:31 +01:00
parent 662483c499
commit bf20e507cd
9 changed files with 175 additions and 167 deletions

168
markdown.py 100644
View File

@ -0,0 +1,168 @@
__filename__ = "markdown.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "1.2.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
__module_group__ = "Web Interface"
def _markdownEmphasisHtml(markdown: str) -> str:
"""Add italics and bold html markup to the given markdown
"""
replacements = {
' **': ' <b>',
'** ': '</b> ',
'**.': '</b>.',
'**:': '</b>:',
'**;': '</b>;',
'**,': '</b>,',
'**\n': '</b>\n',
' *': ' <i>',
'* ': '</i> ',
'*.': '</i>.',
'*:': '</i>:',
'*;': '</i>;',
'*,': '</i>,',
'*\n': '</i>\n',
' _': ' <ul>',
'_ ': '</ul> ',
'_.': '</ul>.',
'_:': '</ul>:',
'_;': '</ul>;',
'_,': '</ul>,',
'_\n': '</ul>\n'
}
for md, html in replacements.items():
markdown = markdown.replace(md, html)
if markdown.startswith('**'):
markdown = markdown[2:] + '<b>'
elif markdown.startswith('*'):
markdown = markdown[1:] + '<i>'
elif markdown.startswith('_'):
markdown = markdown[1:] + '<ul>'
if markdown.endswith('**'):
markdown = markdown[:len(markdown) - 2] + '</b>'
elif markdown.endswith('*'):
markdown = markdown[:len(markdown) - 1] + '</i>'
elif markdown.endswith('_'):
markdown = markdown[:len(markdown) - 1] + '</ul>'
return markdown
def _markdownReplaceQuotes(markdown: str) -> str:
"""Replaces > quotes with html blockquote
"""
if '> ' not in markdown:
return markdown
lines = markdown.split('\n')
result = ''
prevQuoteLine = None
for line in lines:
if '> ' not in line:
result += line + '\n'
prevQuoteLine = None
continue
lineStr = line.strip()
if not lineStr.startswith('> '):
result += line + '\n'
prevQuoteLine = None
continue
lineStr = lineStr.replace('> ', '', 1).strip()
if prevQuoteLine:
newPrevLine = prevQuoteLine.replace('</i></blockquote>\n', '')
result = result.replace(prevQuoteLine, newPrevLine) + ' '
lineStr += '</i></blockquote>\n'
else:
lineStr = '<blockquote><i>' + lineStr + '</i></blockquote>\n'
result += lineStr
prevQuoteLine = lineStr
if '</blockquote>\n' in result:
result = result.replace('</blockquote>\n', '</blockquote>')
if result.endswith('\n') and \
not markdown.endswith('\n'):
result = result[:len(result) - 1]
return result
def _markdownReplaceLinks(markdown: str, images: bool = False) -> str:
"""Replaces markdown links with html
Optionally replace image links
"""
replaceLinks = {}
text = markdown
startChars = '['
if images:
startChars = '!['
while startChars in text:
if ')' not in text:
break
text = text.split(startChars, 1)[1]
markdownLink = startChars + text.split(')')[0] + ')'
if ']' not in markdownLink or \
'(' not in markdownLink:
text = text.split(')', 1)[1]
continue
if not images:
replaceLinks[markdownLink] = \
'<a href="' + \
markdownLink.split('(')[1].split(')')[0] + \
'" target="_blank" rel="nofollow noopener noreferrer">' + \
markdownLink.split(startChars)[1].split(']')[0] + \
'</a>'
else:
replaceLinks[markdownLink] = \
'<img class="markdownImage" src="' + \
markdownLink.split('(')[1].split(')')[0] + \
'" alt="' + \
markdownLink.split(startChars)[1].split(']')[0] + \
'" />'
text = text.split(')', 1)[1]
for mdLink, htmlLink in replaceLinks.items():
markdown = markdown.replace(mdLink, htmlLink)
return markdown
def markdownToHtml(markdown: str) -> str:
"""Converts markdown formatted text to html
"""
markdown = _markdownReplaceQuotes(markdown)
markdown = _markdownEmphasisHtml(markdown)
markdown = _markdownReplaceLinks(markdown, True)
markdown = _markdownReplaceLinks(markdown)
# replace headers
linesList = markdown.split('\n')
htmlStr = ''
ctr = 0
for line in linesList:
if ctr > 0:
htmlStr += '<br>'
if line.startswith('#####'):
line = line.replace('#####', '').strip()
line = '<h5>' + line + '</h5>'
ctr = -1
elif line.startswith('####'):
line = line.replace('####', '').strip()
line = '<h4>' + line + '</h4>'
ctr = -1
elif line.startswith('###'):
line = line.replace('###', '').strip()
line = '<h3>' + line + '</h3>'
ctr = -1
elif line.startswith('##'):
line = line.replace('##', '').strip()
line = '<h2>' + line + '</h2>'
ctr = -1
elif line.startswith('#'):
line = line.replace('#', '').strip()
line = '<h1>' + line + '</h1>'
ctr = -1
htmlStr += line
ctr += 1
return htmlStr

View File

@ -115,8 +115,8 @@ from newswire import parseFeedDate
from mastoapiv1 import getMastoApiV1IdFromNickname from mastoapiv1 import getMastoApiV1IdFromNickname
from mastoapiv1 import getNicknameFromMastoApiV1Id from mastoapiv1 import getNicknameFromMastoApiV1Id
from webapp_post import prepareHtmlPostNickname from webapp_post import prepareHtmlPostNickname
from webapp_utils import markdownToHtml
from speaker import speakerReplaceLinks from speaker import speakerReplaceLinks
from markdown import markdownToHtml
testServerAliceRunning = False testServerAliceRunning = False
testServerBobRunning = False testServerBobRunning = False

View File

@ -12,7 +12,7 @@ from shutil import copyfile
from utils import getConfigParam from utils import getConfigParam
from webapp_utils import htmlHeaderWithWebsiteMarkup from webapp_utils import htmlHeaderWithWebsiteMarkup
from webapp_utils import htmlFooter from webapp_utils import htmlFooter
from webapp_utils import markdownToHtml from markdown import markdownToHtml
def htmlAbout(cssCache: {}, baseDir: str, httpPrefix: str, def htmlAbout(cssCache: {}, baseDir: str, httpPrefix: str,

View File

@ -17,7 +17,7 @@ from utils import isEditor
from utils import removeIdEnding from utils import removeIdEnding
from follow import followerApprovalActive from follow import followerApprovalActive
from person import isPersonSnoozed from person import isPersonSnoozed
from webapp_utils import markdownToHtml from markdown import markdownToHtml
from webapp_utils import htmlKeyboardNavigation from webapp_utils import htmlKeyboardNavigation
from webapp_utils import htmlHideFromScreenReader from webapp_utils import htmlHideFromScreenReader
from webapp_utils import htmlPostSeparator from webapp_utils import htmlPostSeparator

View File

@ -12,7 +12,7 @@ from shutil import copyfile
from utils import getConfigParam from utils import getConfigParam
from webapp_utils import htmlHeaderWithExternalStyle from webapp_utils import htmlHeaderWithExternalStyle
from webapp_utils import htmlFooter from webapp_utils import htmlFooter
from webapp_utils import markdownToHtml from markdown import markdownToHtml
def htmlTermsOfService(cssCache: {}, baseDir: str, def htmlTermsOfService(cssCache: {}, baseDir: str,

View File

@ -22,166 +22,6 @@ from content import replaceEmojiFromTags
from person import getPersonAvatarUrl from person import getPersonAvatarUrl
def _markdownEmphasisHtml(markdown: str) -> str:
"""Add italics and bold html markup to the given markdown
"""
replacements = {
' **': ' <b>',
'** ': '</b> ',
'**.': '</b>.',
'**:': '</b>:',
'**;': '</b>;',
'**,': '</b>,',
'**\n': '</b>\n',
' *': ' <i>',
'* ': '</i> ',
'*.': '</i>.',
'*:': '</i>:',
'*;': '</i>;',
'*,': '</i>,',
'*\n': '</i>\n',
' _': ' <ul>',
'_ ': '</ul> ',
'_.': '</ul>.',
'_:': '</ul>:',
'_;': '</ul>;',
'_,': '</ul>,',
'_\n': '</ul>\n'
}
for md, html in replacements.items():
markdown = markdown.replace(md, html)
if markdown.startswith('**'):
markdown = markdown[2:] + '<b>'
elif markdown.startswith('*'):
markdown = markdown[1:] + '<i>'
elif markdown.startswith('_'):
markdown = markdown[1:] + '<ul>'
if markdown.endswith('**'):
markdown = markdown[:len(markdown) - 2] + '</b>'
elif markdown.endswith('*'):
markdown = markdown[:len(markdown) - 1] + '</i>'
elif markdown.endswith('_'):
markdown = markdown[:len(markdown) - 1] + '</ul>'
return markdown
def _markdownReplaceQuotes(markdown: str) -> str:
"""Replaces > quotes with html blockquote
"""
if '> ' not in markdown:
return markdown
lines = markdown.split('\n')
result = ''
prevQuoteLine = None
for line in lines:
if '> ' not in line:
result += line + '\n'
prevQuoteLine = None
continue
lineStr = line.strip()
if not lineStr.startswith('> '):
result += line + '\n'
prevQuoteLine = None
continue
lineStr = lineStr.replace('> ', '', 1).strip()
if prevQuoteLine:
newPrevLine = prevQuoteLine.replace('</i></blockquote>\n', '')
result = result.replace(prevQuoteLine, newPrevLine) + ' '
lineStr += '</i></blockquote>\n'
else:
lineStr = '<blockquote><i>' + lineStr + '</i></blockquote>\n'
result += lineStr
prevQuoteLine = lineStr
if '</blockquote>\n' in result:
result = result.replace('</blockquote>\n', '</blockquote>')
if result.endswith('\n') and \
not markdown.endswith('\n'):
result = result[:len(result) - 1]
return result
def _markdownReplaceLinks(markdown: str, images: bool = False) -> str:
"""Replaces markdown links with html
Optionally replace image links
"""
replaceLinks = {}
text = markdown
startChars = '['
if images:
startChars = '!['
while startChars in text:
if ')' not in text:
break
text = text.split(startChars, 1)[1]
markdownLink = startChars + text.split(')')[0] + ')'
if ']' not in markdownLink or \
'(' not in markdownLink:
text = text.split(')', 1)[1]
continue
if not images:
replaceLinks[markdownLink] = \
'<a href="' + \
markdownLink.split('(')[1].split(')')[0] + \
'" target="_blank" rel="nofollow noopener noreferrer">' + \
markdownLink.split(startChars)[1].split(']')[0] + \
'</a>'
else:
replaceLinks[markdownLink] = \
'<img class="markdownImage" src="' + \
markdownLink.split('(')[1].split(')')[0] + \
'" alt="' + \
markdownLink.split(startChars)[1].split(']')[0] + \
'" />'
text = text.split(')', 1)[1]
for mdLink, htmlLink in replaceLinks.items():
markdown = markdown.replace(mdLink, htmlLink)
return markdown
def markdownToHtml(markdown: str) -> str:
"""Converts markdown formatted text to html
"""
markdown = _markdownReplaceQuotes(markdown)
markdown = _markdownEmphasisHtml(markdown)
markdown = _markdownReplaceLinks(markdown, True)
markdown = _markdownReplaceLinks(markdown)
# replace headers
linesList = markdown.split('\n')
htmlStr = ''
ctr = 0
for line in linesList:
if ctr > 0:
htmlStr += '<br>'
if line.startswith('#####'):
line = line.replace('#####', '').strip()
line = '<h5>' + line + '</h5>'
ctr = -1
elif line.startswith('####'):
line = line.replace('####', '').strip()
line = '<h4>' + line + '</h4>'
ctr = -1
elif line.startswith('###'):
line = line.replace('###', '').strip()
line = '<h3>' + line + '</h3>'
ctr = -1
elif line.startswith('##'):
line = line.replace('##', '').strip()
line = '<h2>' + line + '</h2>'
ctr = -1
elif line.startswith('#'):
line = line.replace('#', '').strip()
line = '<h1>' + line + '</h1>'
ctr = -1
htmlStr += line
ctr += 1
return htmlStr
def getBrokenLinkSubstitute() -> str: def getBrokenLinkSubstitute() -> str:
"""Returns html used to show a default image if the link to """Returns html used to show a default image if the link to
an image is broken an image is broken

View File

@ -13,7 +13,7 @@ from utils import getConfigParam
from utils import removeHtml from utils import removeHtml
from webapp_utils import htmlHeaderWithExternalStyle from webapp_utils import htmlHeaderWithExternalStyle
from webapp_utils import htmlFooter from webapp_utils import htmlFooter
from webapp_utils import markdownToHtml from markdown import markdownToHtml
def isWelcomeScreenComplete(baseDir: str, nickname: str, domain: str) -> bool: def isWelcomeScreenComplete(baseDir: str, nickname: str, domain: str) -> bool:

View File

@ -13,7 +13,7 @@ from utils import removeHtml
from utils import getConfigParam from utils import getConfigParam
from webapp_utils import htmlHeaderWithExternalStyle from webapp_utils import htmlHeaderWithExternalStyle
from webapp_utils import htmlFooter from webapp_utils import htmlFooter
from webapp_utils import markdownToHtml from markdown import markdownToHtml
def htmlWelcomeFinal(baseDir: str, nickname: str, domain: str, def htmlWelcomeFinal(baseDir: str, nickname: str, domain: str,

View File

@ -16,7 +16,7 @@ from utils import getImageExtensions
from utils import getImageFormats from utils import getImageFormats
from webapp_utils import htmlHeaderWithExternalStyle from webapp_utils import htmlHeaderWithExternalStyle
from webapp_utils import htmlFooter from webapp_utils import htmlFooter
from webapp_utils import markdownToHtml from markdown import markdownToHtml
def htmlWelcomeProfile(baseDir: str, nickname: str, domain: str, def htmlWelcomeProfile(baseDir: str, nickname: str, domain: str,