StreamOverlay/lib/util.gd
Mario Steele e942b41917 Updated Util
Static vars were not being properly created, so instead use a C#
function of '??=', which translates to defining a getter on the
property, checking if it exists, if not, create it and assign it, then
return the value.
Made a duplicate of the string, and did replacements on the new string,
before returning it in html_unescape().
2026-03-09 18:41:40 -05:00

151 lines
4.7 KiB
GDScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

extends Object
class_name Util
#region HTML RegEx and UnEscape HTML
static var _img_re: RegEx:
get():
if not _img_re: _img_re = RegEx.create_from_string(r'<img[^>]*src=["\']([^"\']+)["\'][^>]*/?>', true)
return _img_re
static var _h2_open_re: RegEx:
get():
if not _h2_open_re: _h2_open_re = RegEx.create_from_string(r'<h2[^>]*>', true)
return _h2_open_re
static var _p_open_re: RegEx:
get():
if not _p_open_re: _p_open_re = RegEx.create_from_string(r'<p[^>]*>', true)
return _p_open_re
static var _ul_re: RegEx:
get():
if not _ul_re: _ul_re = RegEx.create_from_string(r'</?ul[^>]*>', true)
return _ul_re
static var _div_re: RegEx:
get():
if not _div_re: _div_re = RegEx.create_from_string(r'</?div[^>]*>', true)
return _div_re
static var _any_tag_re: RegEx:
get():
if not _any_tag_re: _any_tag_re = RegEx.create_from_string(r'<[^>]*>', true)
return _any_tag_re
static var _html_replacements: Dictionary[String, String]:
get():
if not _html_replacements: _html_replacements = {
"&lt;": "<", "&gt;": ">", "&amp;": "&", "&quot;": "\"",
"&#39;": "'", "&#x27;": "'", "&#x2F;": "/", "&#96;": "`",
"&nbsp;": " ", "&copy;": "©", "&reg;": "®", "&euro;": "",
"&pound;": "£", "&yen;": "¥", "&ndash;": "", "&mdash;": "",
"&lsquo;": "", "&rsquo;": "", "&ldquo;": "", "&rdquo;": "",
"&hellip;": "", "&bull;": ""
}
return _html_replacements
#endregion
static func convert_html_to_bbcode(html: String) -> String:
# NOTE: Unescape HTML entities
var bb = html_unescape(html)
# NOTE: Replace <img ... src="..."> with [img]...[/img]
bb = _img_re.sub(bb, "[img]$1[/img]", true)
# NOTE: Replace <h2 ...>...</h2> tags, with [b]...[/b]
bb = _h2_open_re.sub(bb, "[b]", true)
bb = bb.replace("</h2>", "[/b]\n")
# NOTE: Remove <p> tags, convert </p> to new line
bb = _p_open_re.sub(bb, "", true)
bb = bb.replace("</p>", "\n")
# NOTE: List Items: <li> -> •, </li> -> newline
bb = bb.replace("<li>", "")
bb = bb.replace("</li>", "\n")
# NOTE: Remove <ul> and </ul>
bb = _ul_re.sub(bb, "", true)
# NOTE: Remove <div ...> and </div>
bb = _div_re.sub(bb, "", true)
# NOTE: Remove any remaining tags
bb = _any_tag_re.sub(bb, "", true)
# NOTE: Trim and normalize spacing
bb = bb.strip_edges()
bb = bb.replace("\n\n\n", "\n\n")
return bb
static func html_unescape(text: String) -> String:
var new_text: String = String(text)
for key: String in _html_replacements.keys():
new_text = new_text.replace(key, _html_replacements[key])
return new_text
static func resize_img_to_max_dim(img: Image, max_dim: int) -> Image:
var width: int
var height: int
var _is_taller: bool = img.get_size().x < img.get_size().y
if _is_taller:
@warning_ignore("integer_division")
width = (max_dim * img.get_size().x) / img.get_size().y
height = max_dim
else:
width = max_dim
@warning_ignore("integer_division")
height = (max_dim * img.get_size().y) / img.get_size().x
var resized_image: Image = img.duplicate()
resized_image.resize(width, height)
return resized_image
#region Time Parsers
const WEEKDAYS = ["Sun","Mon","Tue", "Wed", "Thu", "Fri", "Sat"]
const MONTHS_SHORT = ["Jan","Feb","Mar","Apr","May", "Jun","Jul","Aug","Sep","Oct","Nov","Dec"]
const FORMAT_STRING_TIME = "%d:%02d:%02d"
const FORMAT_STRING_DATE = "{day} {month} {year}"
const FORMAT_STRING_DATE_FILE = "{year}_{month}_{day}"
const FORMAT_STRING_TIME_FILE = "%d_%02d_%02d"
static func unix_to_string(
unix: float,
include_weekday := true,
include_time := true,
dz_enabled := true) -> String:
if !unix: return "Never"
if dz_enabled:
var tz_offset_usec = Time.get_time_zone_from_system().bias * 60
unix += tz_offset_usec
var dict: Dictionary = Time.get_datetime_dict_from_unix_time(floori(unix))
dict.weekday = WEEKDAYS[dict.weekday]
dict.month = MONTHS_SHORT[dict.month-1]
var format_string: String = FORMAT_STRING_DATE
if include_weekday:
format_string = "{weekday} " + format_string
if include_time:
var time_string: String = (FORMAT_STRING_TIME % [dict.hour, dict.minute, dict.second])
format_string = format_string + " - " + time_string
return format_string.format(dict)
static func unix_to_string_filepath(unix: float, include_time := false) -> String:
if !unix: return "Never"
var tz_offset_usec = Time.get_time_zone_from_system().bias * 60
unix += tz_offset_usec
var dict: Dictionary = Time.get_datetime_dict_from_unix_time(floori(unix))
dict.weekday = WEEKDAYS[dict.weekday]
dict.month = MONTHS_SHORT[dict.month-1]
var format_string: String = FORMAT_STRING_DATE_FILE.format(dict)
if include_time:
var time_string: String = (FORMAT_STRING_TIME_FILE % [dict.hour, dict.minute, dict.second])
format_string += "_" + time_string
return format_string
#endregion