mirror of https://gitlab.com/bashrc2/epicyon
Move markdown functions to a separate module
parent
662483c499
commit
bf20e507cd
|
@ -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
|
2
tests.py
2
tests.py
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
160
webapp_utils.py
160
webapp_utils.py
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue