collapse whitespace between block babycode tags

This commit is contained in:
2025-08-16 16:59:44 +03:00
parent cf89070639
commit 9238385244
2 changed files with 48 additions and 5 deletions

View File

@ -35,13 +35,17 @@ NAMED_COLORS = [
'violet', 'wheat', 'white', 'whitesmoke', 'yellow', 'yellowgreen',
]
def is_tag(e, tag):
def is_tag(e, tag=None):
if e is None:
return False
if isinstance(e, str):
return False
if e['type'] != 'bbcode':
return False
if tag is None:
return True
return e['name'] == tag
def is_text(e):
@ -112,6 +116,12 @@ TAGS = {
"spoiler": tag_spoiler,
}
# [img] and [code] are considered block for the purposes of collapsing whitespace,
# despite being potentially inline ([img] is particularly egregious, since the resulting <img> tag is inline, but creates a block container around itself and sibling images)
INLINE_TAGS = {
'b', 'i', 's', 'u', 'color', 'big', 'small', 'url'
}
def make_emoji(name, code):
return f' <img class=emoji src="/static/emoji/{name}.png" alt="{name}" title=":{code}:">'
@ -168,6 +178,30 @@ def break_lines(text):
text = re.sub(r"\n\n+", "<br><br>", text)
return text
def is_inline(e):
if e is None:
return False # i think
if is_text(e):
return True
if is_tag(e):
return e['name'] in INLINE_TAGS
return e['type'] != 'rule'
def should_collapse(text, surrounding):
if not isinstance(text, str):
return False
if not text:
return True
if not text.strip() and '\n' not in text:
return not is_inline(surrounding[0]) and not is_inline(surrounding[1])
return False
def babycode_to_html(s):
subj = escape(s.strip().replace('\r\n', '\n').replace('\r', '\n'))
parser = Parser(subj)
@ -175,7 +209,17 @@ def babycode_to_html(s):
parser.bbcode_tags_only_text_children = TEXT_ONLY
parser.valid_emotes = EMOJI.keys()
elements = parser.parse()
uncollapsed = parser.parse()
elements = []
for i in range(len(uncollapsed)):
e = uncollapsed[i]
surrounding = (
uncollapsed[i - 1] if i-1 >= 0 else None,
uncollapsed[i + 1] if i+1 < len(uncollapsed) else None
)
if not should_collapse(e, surrounding):
elements.append(e)
out = ""
def fold(element, nobr, surrounding):
if isinstance(element, str):
@ -203,8 +247,7 @@ def babycode_to_html(s):
return EMOJI[element['name']]
case "rule":
return "<hr>"
# for e in elements:
# out = out + fold(e, False)
for i in range(len(elements)):
e = elements[i]
surrounding = (