diff --git a/app/lib/babycode.py b/app/lib/babycode.py
index 747f668..13e4a8f 100644
--- a/app/lib/babycode.py
+++ b/app/lib/babycode.py
@@ -141,6 +141,12 @@ TAGS = {
"spoiler": tag_spoiler,
}
+VOID_TAGS = {
+ 'lb': lambda attr: '[',
+ 'rb': lambda attr: ']',
+ '@': lambda attr: '@',
+}
+
# [img] is considered block for the purposes of collapsing whitespace,
# despite being potentially inline (since the resulting tag is inline, but creates a block container around itself and sibling images).
# [code] has a special case in is_inline().
@@ -260,6 +266,7 @@ def babycode_to_html(s, banned_tags=[]):
subj = sanitize(s)
parser = Parser(subj)
parser.valid_bbcode_tags = allowed_tags
+ parser.void_bbcode_tags = set(VOID_TAGS)
parser.bbcode_tags_only_text_children = TEXT_ONLY
parser.mentions_allowed = '@mention' not in banned_tags
parser.valid_emotes = EMOJI.keys()
@@ -296,6 +303,8 @@ def babycode_to_html(s, banned_tags=[]):
c = c + Markup(fold(child, _nobr, _surrounding))
res = TAGS[element['name']](c, element['attr'], surrounding)
return res
+ case "bbcode_void":
+ return VOID_TAGS[element['name']](element['attr'])
case "link":
return f"{element['url']}"
case 'emote':
diff --git a/app/lib/babycode_parser.py b/app/lib/babycode_parser.py
index a858f05..b784249 100644
--- a/app/lib/babycode_parser.py
+++ b/app/lib/babycode_parser.py
@@ -11,6 +11,7 @@ PAT_MENTION = r'[a-zA-Z0-9_-]'
class Parser:
def __init__(self, src_str):
self.valid_bbcode_tags = {}
+ self.void_bbcode_tags = {}
self.valid_emotes = []
self.bbcode_tags_only_text_children = []
self.mentions_allowed = True
@@ -228,11 +229,46 @@ class Parser:
}
+ def parse_bbcode_void(self):
+ self.save_position()
+
+ if not self.check_char("["):
+ self.restore_position()
+ return None
+
+ name = self.match_pattern(PAT_BBCODE_TAG)
+
+ if name == "":
+ self.restore_position()
+ return None
+
+ attr = None
+
+ if self.check_char("="):
+ attr = self.match_pattern(PAT_BBCODE_ATTR)
+
+ if not self.check_char("]"):
+ self.restore_position()
+ return None
+
+ if not name in self.void_bbcode_tags:
+ self.restore_position()
+ return None
+
+ self.forget_position()
+ return {
+ 'type': 'bbcode_void',
+ 'name': name,
+ 'attr': attr,
+ }
+
+
def parse_element(self, siblings):
if self.is_end_of_source():
return None
element = self.parse_emote() \
+ or self.parse_bbcode_void() \
or self.parse_bbcode() \
or self.parse_rule() \
or self.parse_link() \
diff --git a/app/templates/guides/babycode.html b/app/templates/guides/babycode.html
index 5ae0f25..8522c72 100644
--- a/app/templates/guides/babycode.html
+++ b/app/templates/guides/babycode.html
@@ -173,6 +173,19 @@
Your display name
Mentioning a user does not notify them. It is simply a way to link to their profile in your posts.
+The special void tags [lb], [rb], and [@] will appear as the literal characters [, ], and @ respectively. Unlike other tags, they are self-contained and have no closing equivalent.
[lb] and [rb] allow you to use square brackets without them being interpreted as Babycode:
+ {{ ("[code]" + lbrb + "[/code]") | babycode | safe }}
+ Will result in:[@] tag allows you to use the @ symbol without it being turned into a mention.