pyrom/app/lib/babycode.py

118 lines
3.7 KiB
Python

from .babycode_parser import Parser
from markupsafe import escape
import re
def tag_code(children, attr):
is_inline = children.find('\n') == -1
if is_inline:
return f"<code class=\"inline_code\">{children}</code>"
else:
t = children.strip()
button = f"<button type=button class=\"copy-code\" value={t}>Copy</button>"
return f"<pre><span class=\"copy-code-container\">{button}</span><code>{t}</code></pre>"
def tag_list(children):
list_body = re.sub(r" +\n", "<br>", children.strip())
list_body = re.sub(r"\n\n+", "\1", list_body)
return " ".join([f"<li>{x}</li>" for x in list_body.split("\1") if x])
TAGS = {
"b": lambda children, attr: f"<strong>{children}</strong>",
"i": lambda children, attr: f"<em>{children}</em>",
"s": lambda children, attr: f"<del>{children}</del>",
"img": lambda children, attr: f"<div class=\"post-img-container\"><img class=\"block-img\" src={attr} alt={children}></div>",
"url": lambda children, attr: f"<a href={attr}>{children}</a>",
"quote": lambda children, attr: f"<blockquote>{children}</blockquote>",
"code": tag_code,
"ul": lambda children, attr: f"<ul>{tag_list(children)}</ul>",
"ol": lambda children, attr: f"<ol>{tag_list(children)}</ol>",
}
def make_emoji(name, code):
return f' <img class=emoji src="/static/emoji/{name}.png" alt="{name}" title=":{code}:">'
EMOJI = {
'angry': make_emoji('angry', 'angry'),
'(': make_emoji('frown', '('),
'D': make_emoji('grin', 'D'),
'imp': make_emoji('imp', 'imp'),
'angryimp': make_emoji('impangry', 'angryimp'),
'impangry': make_emoji('impangry', 'impangry'),
'lobster': make_emoji('lobster', 'lobster'),
'|': make_emoji('neutral', '|'),
'pensive': make_emoji('pensive', 'pensive'),
')': make_emoji('smile', ')'),
'smiletear': make_emoji('smiletear', 'smiletear'),
'crytear': make_emoji('smiletear', 'crytear'),
',': make_emoji('sob', ','),
'T': make_emoji('sob', 'T'),
'cry': make_emoji('sob', 'cry'),
'sob': make_emoji('sob', 'sob'),
'o': make_emoji('surprised', 'o'),
'O': make_emoji('surprised', 'O'),
'hmm': make_emoji('think', 'hmm'),
'think': make_emoji('think', 'think'),
'thinking': make_emoji('think', 'thinking'),
'P': make_emoji('tongue', 'P'),
'p': make_emoji('tongue', 'p'),
'weary': make_emoji('weary', 'weary'),
';': make_emoji('wink', ';'),
'wink': make_emoji('wink', 'wink'),
}
TEXT_ONLY = ["code"]
def break_lines(text):
text = re.sub(r" +\n", "<br>", text)
text = re.sub(r"\n\n+", "<br><br>", text)
return text
def babycode_to_html(s):
subj = escape(s.strip().replace('\r\n', '\n').replace('\r', '\n'))
parser = Parser(subj)
parser.valid_bbcode_tags = TAGS.keys()
parser.bbcode_tags_only_text_children = TEXT_ONLY
parser.valid_emotes = EMOJI.keys()
elements = parser.parse()
print(elements)
out = ""
def fold(element, nobr):
if isinstance(element, str):
if nobr:
return element
return break_lines(element)
match element['type']:
case "bbcode":
c = ""
for child in element['children']:
_nobr = element['name'] == "code" or element['name'] == "ul" or element['name'] == "ol"
c = c + fold(child, _nobr)
res = TAGS[element['name']](c, element['attr'])
return res
case "link":
return f"<a href=\"{element['url']}\">{element['url']}</a>"
case 'emote':
return EMOJI[element['name']]
case "rule":
return "<hr>"
for e in elements:
out = out + fold(e, False)
return out