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']*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']*>', 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']*>', true) return _p_open_re static var _ul_re: RegEx: get(): if not _ul_re: _ul_re = RegEx.create_from_string(r']*>', true) return _ul_re static var _div_re: RegEx: get(): if not _div_re: _div_re = RegEx.create_from_string(r']*>', 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 = { "<": "<", ">": ">", "&": "&", """: "\"", "'": "'", "'": "'", "/": "/", "`": "`", " ": " ", "©": "©", "®": "®", "€": "€", "£": "£", "¥": "¥", "–": "–", "—": "—", "‘": "‘", "’": "’", "“": "“", "”": "”", "…": "…", "•": "•" } return _html_replacements #endregion static func convert_html_to_bbcode(html: String) -> String: # NOTE: Unescape HTML entities var bb = html_unescape(html) # NOTE: Replace with [img]...[/img] bb = _img_re.sub(bb, "[img]$1[/img]", true) # NOTE: Replace

...

tags, with [b]...[/b] bb = _h2_open_re.sub(bb, "[b]", true) bb = bb.replace("", "[/b]\n") # NOTE: Remove

tags, convert

to new line bb = _p_open_re.sub(bb, "", true) bb = bb.replace("

", "\n") # NOTE: List Items:
  • -> •,
  • -> newline bb = bb.replace("
  • ", "• ") bb = bb.replace("
  • ", "\n") # NOTE: Remove
      and
    bb = _ul_re.sub(bb, "", true) # NOTE: Remove
    and
    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