Last active
January 4, 2024 22:24
-
-
Save dalexeev/cfcb94a41e80de301cc595b74f7b5ebd to your computer and use it in GitHub Desktop.
GDScript BBCode parser/preprocessor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This option roughly matches the described requirements of `get_parsed_text()` emulation. | |
# See https://github.com/godotengine/godot/blob/179dfdc8d78b5bd5377dd115af026df58308bdaf/scene/gui/rich_text_label.cpp#L3999. | |
const TAGS_TO_STRIP: Array[String] = [ | |
"b", "i", "code", "table", "cell", "u", "s", "center", "fill", "left", "right", | |
"ul", "ol", "lang", "p", "url", "hint", "dropcap", "color", "outline_color", | |
"font_size", "opentype_features", "otf", "font", "outline_size", "fade", "shake", | |
"wave", "tornado", "rainbow", "pulse", "bgcolor", "fgcolor", | |
] | |
const TAGS_TO_REPLACE: Dictionary = { | |
"lb": "[", | |
"rb": "]", | |
"lrm": "\u200E", | |
"rlm": "\u200F", | |
"lre": "\u202A", | |
"rle": "\u202B", | |
"lro": "\u202D", | |
"rlo": "\u202E", | |
"pdf": "\u202C", | |
"alm": "\u061c", | |
"lri": "\u2066", | |
"rli": "\u2027", | |
"fsi": "\u2068", | |
"pdi": "\u2069", | |
"zwj": "\u200D", | |
"zwnj": "\u200C", | |
"wj": "\u2060", | |
"shy": "\u00AD", | |
"img": "", | |
} | |
func preprocess_bbcode(input: String) -> String: | |
var output: String = "" | |
var pos: int = 0 | |
var tag_stack: Array[String] = [] | |
while true: | |
var lb_pos: int = input.find("[", pos) | |
if lb_pos < 0: | |
break | |
var rb_pos: int = input.find("]", lb_pos + 1) | |
if rb_pos < 0: | |
break | |
output += input.substr(pos, lb_pos - pos) | |
pos = rb_pos + 1 | |
var tag: String = input.substr(lb_pos + 1, rb_pos - lb_pos - 1) | |
if tag.begins_with("/"): | |
if tag_stack.is_empty() or tag.trim_prefix("/") != tag_stack[-1]: | |
output += "[" + tag + "]" | |
else: | |
tag_stack.pop_back() | |
else: | |
var tag_name: String = tag.get_slice(" ", 0).get_slice("=", 0) | |
if TAGS_TO_STRIP.has(tag_name): | |
tag_stack.push_back(tag_name) | |
elif TAGS_TO_REPLACE.has(tag_name): | |
output += TAGS_TO_REPLACE[tag_name] | |
else: | |
output += "[" + tag + "]" | |
return output + input.substr(pos) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This option is designed to handle pseudo-tags. The rest of the tags are saved as is, | |
# you can add a check only for individual tags, for example `[url]`. | |
const SINGLE_TAGS: Array[String] = [ | |
"lb", "rb", "lrm", "rlm", "lre", "rle", "lro", "rlo", "pdf", "alm", "lri", "rli", | |
"fsi", "pdi", "zwj", "zwnj", "wj", "shy", "img", | |
] | |
func preprocess_bbcode(input: String) -> String: | |
var output: String = "" | |
var pos: int = 0 | |
var tag_stack: Array[String] = [] | |
while true: | |
var lb_pos: int = input.find("[", pos) | |
if lb_pos < 0: | |
break | |
var rb_pos: int = input.find("]", lb_pos + 1) | |
if rb_pos < 0: | |
break | |
output += input.substr(pos, lb_pos - pos) | |
pos = rb_pos + 1 | |
var tag: String = input.substr(lb_pos + 1, rb_pos - lb_pos - 1) | |
if tag.begins_with("/"): | |
if tag_stack.is_empty() or tag.trim_prefix("/") != tag_stack[-1]: | |
output += "[lb]" + tag + "]" # Escape the tag just in case. | |
else: | |
if tag == "/user": | |
output += "[/color][/b][/url]" | |
elif tag == "/item": | |
output += "[/color][/url]" | |
elif tag == "/url": | |
output += "[lb]/url]" | |
tag_stack.pop_back() | |
else: | |
var tag_name: String = tag.get_slice(" ", 0).get_slice("=", 0) | |
var params: String = tag.substr(tag_name.length() + 1) | |
if not SINGLE_TAGS.has(tag_name): | |
tag_stack.push_back(tag_name) | |
if tag_name == "user": | |
output += "[url=user:%s][b][color=blue]" % params | |
elif tag_name == "item": | |
output += "[url=item:%s][img=res://items/%s.png][color=green]" % [params, params] | |
elif tag_name == "url": | |
output += ("[" + tag + "]").replace("[", "[lb]") | |
else: | |
output += "[" + tag + "]" # Leave it as is, regardless of the validity. | |
return output + input.substr(pos) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment