diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c805ddb --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +preview.html \ No newline at end of file diff --git a/fonts/ChaletComprime_CologneSixty.ttf b/fonts/ChaletComprime_CologneSixty.ttf new file mode 100644 index 0000000..5b5da49 Binary files /dev/null and b/fonts/ChaletComprime_CologneSixty.ttf differ diff --git a/fonts/ChaletLondonNineteenSixty.ttf b/fonts/ChaletLondonNineteenSixty.ttf new file mode 100644 index 0000000..48ff6ad Binary files /dev/null and b/fonts/ChaletLondonNineteenSixty.ttf differ diff --git a/main.xml b/main.xml index 0eb64c7..e3cb87f 100644 --- a/main.xml +++ b/main.xml @@ -434,7 +434,7 @@ 🛡️ ~b~GTA CnR Shield ~s~baneo {0} por {1} por ~r~{2}~s~. Total de jugadores baneados: {3} 🛡️ ~b~GTA CnR Shield ~s~a banni {0} pendant {1} pour ~r~{2}~s~. Total de joueurs bannis: {3} 🛡️ ~b~GTA CnR Shield ~s~hat {0} für {1} wegen ~r~{2}~s~ gebannt. Insgesamt gebannte Spieler: {3} - 🛡️ ~b~GTA CnR Shield ~s~~baneo {0} por {1} por ~r~{2}~s~. Total de jogadores banidos: {3} + 🛡️ ~b~GTA CnR Shield ~s~baneo {0} por {1} por ~r~{2}~s~. Total de jogadores banidos: {3} diff --git a/validator.py b/validator.py index 32e0f41..bf61084 100644 --- a/validator.py +++ b/validator.py @@ -5,17 +5,282 @@ import xml.sax import re -USE_COLORAMA = True +COLORAMA_INSTALLED = True +DOMINATE_INSTALLED = True + try: import colorama except ModuleNotFoundError: - USE_COLORAMA = False + COLORAMA_INSTALLED = False +try: + import dominate + import dominate.tags +except ModuleNotFoundError: + DOMINATE_INSTALLED = False + +GTA_HUD_COLORS = { + "HUD_COLOUR_PURE_WHITE": "rgba(255, 255, 255, 255)", + "HUD_COLOUR_WHITE": "rgba(240, 240, 240, 255)", + "HUD_COLOUR_BLACK": "rgba(0, 0, 0, 255)", + "HUD_COLOUR_GREY": "rgba(155, 155, 155, 255)", + "HUD_COLOUR_GREYLIGHT": "rgba(205, 205, 205, 255)", + "HUD_COLOUR_GREYDARK": "rgba(77, 77, 77, 255)", + "HUD_COLOUR_RED": "rgba(224, 50, 50, 255)", + "HUD_COLOUR_REDLIGHT": "rgba(240, 153, 153, 255)", + "HUD_COLOUR_REDDARK": "rgba(112, 25, 25, 255)", + "HUD_COLOUR_BLUE": "rgba(93, 182, 229, 255)", + "HUD_COLOUR_BLUELIGHT": "rgba(174, 219, 242, 255)", + "HUD_COLOUR_BLUEDARK": "rgba(47, 92, 115, 255)", + "HUD_COLOUR_YELLOW": "rgba(240, 200, 80, 255)", + "HUD_COLOUR_YELLOWLIGHT": "rgba(254, 235, 169, 255)", + "HUD_COLOUR_YELLOWDARK": "rgba(126, 107, 41, 255)", + "HUD_COLOUR_ORANGE": "rgba(255, 133, 85, 255)", + "HUD_COLOUR_ORANGELIGHT": "rgba(255, 194, 170, 255)", + "HUD_COLOUR_ORANGEDARK": "rgba(127, 66, 42, 255)", + "HUD_COLOUR_GREEN": "rgba(114, 204, 114, 255)", + "HUD_COLOUR_GREENLIGHT": "rgba(185, 230, 185, 255)", + "HUD_COLOUR_GREENDARK": "rgba(57, 102, 57, 255)", + "HUD_COLOUR_PURPLE": "rgba(132, 102, 226, 255)", + "HUD_COLOUR_PURPLELIGHT": "rgba(192, 179, 239, 255)", + "HUD_COLOUR_PURPLEDARK": "rgba(67, 57, 111, 255)", + "HUD_COLOUR_PINK": "rgba(203, 54, 148, 255)", + "HUD_COLOUR_RADAR_HEALTH": "rgba(53, 154, 71, 255)", + "HUD_COLOUR_RADAR_ARMOUR": "rgba(93, 182, 229, 255)", + "HUD_COLOUR_RADAR_DAMAGE": "rgba(235, 36, 39, 255)", + "HUD_COLOUR_NET_PLAYER1": "rgba(194, 80, 80, 255)", + "HUD_COLOUR_NET_PLAYER2": "rgba(156, 110, 175, 255)", + "HUD_COLOUR_NET_PLAYER3": "rgba(255, 123, 196, 255)", + "HUD_COLOUR_NET_PLAYER4": "rgba(247, 159, 123, 255)", + "HUD_COLOUR_NET_PLAYER5": "rgba(178, 144, 132, 255)", + "HUD_COLOUR_NET_PLAYER6": "rgba(141, 206, 167, 255)", + "HUD_COLOUR_NET_PLAYER7": "rgba(113, 169, 175, 255)", + "HUD_COLOUR_NET_PLAYER8": "rgba(211, 209, 231, 255)", + "HUD_COLOUR_NET_PLAYER9": "rgba(144, 127, 153, 255)", + "HUD_COLOUR_NET_PLAYER10": "rgba(106, 196, 191, 255)", + "HUD_COLOUR_NET_PLAYER11": "rgba(214, 196, 153, 255)", + "HUD_COLOUR_NET_PLAYER12": "rgba(234, 142, 80, 255)", + "HUD_COLOUR_NET_PLAYER13": "rgba(152, 203, 234, 255)", + "HUD_COLOUR_NET_PLAYER14": "rgba(178, 98, 135, 255)", + "HUD_COLOUR_NET_PLAYER15": "rgba(144, 142, 122, 255)", + "HUD_COLOUR_NET_PLAYER16": "rgba(166, 117, 94, 255)", + "HUD_COLOUR_NET_PLAYER17": "rgba(175, 168, 168, 255)", + "HUD_COLOUR_NET_PLAYER18": "rgba(232, 142, 155, 255)", + "HUD_COLOUR_NET_PLAYER19": "rgba(187, 214, 91, 255)", + "HUD_COLOUR_NET_PLAYER20": "rgba(12, 123, 86, 255)", + "HUD_COLOUR_NET_PLAYER21": "rgba(123, 196, 255, 255)", + "HUD_COLOUR_NET_PLAYER22": "rgba(171, 60, 230, 255)", + "HUD_COLOUR_NET_PLAYER23": "rgba(206, 169, 13, 255)", + "HUD_COLOUR_NET_PLAYER24": "rgba(71, 99, 173, 255)", + "HUD_COLOUR_NET_PLAYER25": "rgba(42, 166, 185, 255)", + "HUD_COLOUR_NET_PLAYER26": "rgba(186, 157, 125, 255)", + "HUD_COLOUR_NET_PLAYER27": "rgba(201, 225, 255, 255)", + "HUD_COLOUR_NET_PLAYER28": "rgba(240, 240, 150, 255)", + "HUD_COLOUR_NET_PLAYER29": "rgba(237, 140, 161, 255)", + "HUD_COLOUR_NET_PLAYER30": "rgba(249, 138, 138, 255)", + "HUD_COLOUR_NET_PLAYER31": "rgba(252, 239, 166, 255)", + "HUD_COLOUR_NET_PLAYER32": "rgba(240, 240, 240, 255)", + "HUD_COLOUR_SIMPLEBLIP_DEFAULT": "rgba(159, 201, 166, 255)", + "HUD_COLOUR_MENU_BLUE": "rgba(140, 140, 140, 255)", + "HUD_COLOUR_MENU_GREY_LIGHT": "rgba(140, 140, 140, 255)", + "HUD_COLOUR_MENU_BLUE_EXTRA_DARK": "rgba(40, 40, 40, 255)", + "HUD_COLOUR_MENU_YELLOW": "rgba(240, 160, 0, 255)", + "HUD_COLOUR_MENU_YELLOW_DARK": "rgba(240, 160, 0, 255)", + "HUD_COLOUR_MENU_GREEN": "rgba(240, 160, 0, 255)", + "HUD_COLOUR_MENU_GREY": "rgba(140, 140, 140, 255)", + "HUD_COLOUR_MENU_GREY_DARK": "rgba(60, 60, 60, 255)", + "HUD_COLOUR_MENU_HIGHLIGHT": "rgba(30, 30, 30, 255)", + "HUD_COLOUR_MENU_STANDARD": "rgba(140, 140, 140, 255)", + "HUD_COLOUR_MENU_DIMMED": "rgba(75, 75, 75, 255)", + "HUD_COLOUR_MENU_EXTRA_DIMMED": "rgba(50, 50, 50, 255)", + "HUD_COLOUR_BRIEF_TITLE": "rgba(95, 95, 95, 255)", + "HUD_COLOUR_MID_GREY_MP": "rgba(100, 100, 100, 255)", + "HUD_COLOUR_NET_PLAYER1_DARK": "rgba(93, 39, 39, 255)", + "HUD_COLOUR_NET_PLAYER2_DARK": "rgba(77, 55, 89, 255)", + "HUD_COLOUR_NET_PLAYER3_DARK": "rgba(124, 62, 99, 255)", + "HUD_COLOUR_NET_PLAYER4_DARK": "rgba(120, 80, 80, 255)", + "HUD_COLOUR_NET_PLAYER5_DARK": "rgba(87, 72, 66, 255)", + "HUD_COLOUR_NET_PLAYER6_DARK": "rgba(74, 103, 83, 255)", + "HUD_COLOUR_NET_PLAYER7_DARK": "rgba(60, 85, 88, 255)", + "HUD_COLOUR_NET_PLAYER8_DARK": "rgba(105, 105, 64, 255)", + "HUD_COLOUR_NET_PLAYER9_DARK": "rgba(72, 63, 76, 255)", + "HUD_COLOUR_NET_PLAYER10_DARK": "rgba(53, 98, 95, 255)", + "HUD_COLOUR_NET_PLAYER11_DARK": "rgba(107, 98, 76, 255)", + "HUD_COLOUR_NET_PLAYER12_DARK": "rgba(117, 71, 40, 255)", + "HUD_COLOUR_NET_PLAYER13_DARK": "rgba(76, 101, 117, 255)", + "HUD_COLOUR_NET_PLAYER14_DARK": "rgba(65, 35, 47, 255)", + "HUD_COLOUR_NET_PLAYER15_DARK": "rgba(72, 71, 61, 255)", + "HUD_COLOUR_NET_PLAYER16_DARK": "rgba(85, 58, 47, 255)", + "HUD_COLOUR_NET_PLAYER17_DARK": "rgba(87, 84, 84, 255)", + "HUD_COLOUR_NET_PLAYER18_DARK": "rgba(116, 71, 77, 255)", + "HUD_COLOUR_NET_PLAYER19_DARK": "rgba(93, 107, 45, 255)", + "HUD_COLOUR_NET_PLAYER20_DARK": "rgba(6, 61, 43, 255)", + "HUD_COLOUR_NET_PLAYER21_DARK": "rgba(61, 98, 127, 255)", + "HUD_COLOUR_NET_PLAYER22_DARK": "rgba(85, 30, 115, 255)", + "HUD_COLOUR_NET_PLAYER23_DARK": "rgba(103, 84, 6, 255)", + "HUD_COLOUR_NET_PLAYER24_DARK": "rgba(35, 49, 86, 255)", + "HUD_COLOUR_NET_PLAYER25_DARK": "rgba(21, 83, 92, 255)", + "HUD_COLOUR_NET_PLAYER26_DARK": "rgba(93, 98, 62, 255)", + "HUD_COLOUR_NET_PLAYER27_DARK": "rgba(100, 112, 127, 255)", + "HUD_COLOUR_NET_PLAYER28_DARK": "rgba(120, 120, 75, 255)", + "HUD_COLOUR_NET_PLAYER29_DARK": "rgba(152, 76, 93, 255)", + "HUD_COLOUR_NET_PLAYER30_DARK": "rgba(124, 69, 69, 255)", + "HUD_COLOUR_NET_PLAYER31_DARK": "rgba(10, 43, 50, 255)", + "HUD_COLOUR_NET_PLAYER32_DARK": "rgba(95, 95, 10, 255)", + "HUD_COLOUR_BRONZE": "rgba(180, 130, 97, 255)", + "HUD_COLOUR_SILVER": "rgba(150, 153, 161, 255)", + "HUD_COLOUR_GOLD": "rgba(214, 181, 99, 255)", + "HUD_COLOUR_PLATINUM": "rgba(166, 221, 190, 255)", + "HUD_COLOUR_GANG1": "rgba(29, 100, 153, 255)", + "HUD_COLOUR_GANG2": "rgba(214, 116, 15, 255)", + "HUD_COLOUR_GANG3": "rgba(135, 125, 142, 255)", + "HUD_COLOUR_GANG4": "rgba(229, 119, 185, 255)", + "HUD_COLOUR_SAME_CREW": "rgba(252, 239, 166, 255)", + "HUD_COLOUR_FREEMODE": "rgba(45, 110, 185, 255)", + "HUD_COLOUR_PAUSE_BG": "rgba(0, 0, 0, 186)", + "HUD_COLOUR_FRIENDLY": "rgba(93, 182, 229, 255)", + "HUD_COLOUR_ENEMY": "rgba(194, 80, 80, 255)", + "HUD_COLOUR_LOCATION": "rgba(240, 200, 80, 255)", + "HUD_COLOUR_PICKUP": "rgba(114, 204, 114, 255)", + "HUD_COLOUR_PAUSE_SINGLEPLAYER": "rgba(114, 204, 114, 255)", + "HUD_COLOUR_FREEMODE_DARK": "rgba(22, 55, 92, 255)", + "HUD_COLOUR_INACTIVE_MISSION": "rgba(154, 154, 154, 255)", + "HUD_COLOUR_DAMAGE": "rgba(194, 80, 80, 255)", + "HUD_COLOUR_PINKLIGHT": "rgba(252, 115, 201, 255)", + "HUD_COLOUR_PM_MITEM_HIGHLIGHT": "rgba(252, 177, 49, 255)", + "HUD_COLOUR_SCRIPT_VARIABLE": "rgba(0, 0, 0, 255)", + "HUD_COLOUR_YOGA": "rgba(109, 247, 204, 255)", + "HUD_COLOUR_TENNIS": "rgba(241, 101, 34, 255)", + "HUD_COLOUR_GOLF": "rgba(214, 189, 97, 255)", + "HUD_COLOUR_SHOOTING_RANGE": "rgba(112, 25, 25, 255)", + "HUD_COLOUR_FLIGHT_SCHOOL": "rgba(47, 92, 115, 255)", + "HUD_COLOUR_NORTH_BLUE": "rgba(93, 182, 229, 255)", + "HUD_COLOUR_SOCIAL_CLUB": "rgba(234, 153, 28, 255)", + "HUD_COLOUR_PLATFORM_BLUE": "rgba(11, 55, 123, 255)", + "HUD_COLOUR_PLATFORM_GREEN": "rgba(146, 200, 62, 255)", + "HUD_COLOUR_PLATFORM_GREY": "rgba(234, 153, 28, 255)", + "HUD_COLOUR_FACEBOOK_BLUE": "rgba(66, 89, 148, 255)", + "HUD_COLOUR_INGAME_BG": "rgba(0, 0, 0, 186)", + "HUD_COLOUR_DARTS": "rgba(114, 204, 114, 255)", + "HUD_COLOUR_WAYPOINT": "rgba(164, 76, 242, 255)", + "HUD_COLOUR_MICHAEL": "rgba(101, 180, 212, 255)", + "HUD_COLOUR_FRANKLIN": "rgba(171, 237, 171, 255)", + "HUD_COLOUR_TREVOR": "rgba(255, 163, 87, 255)", + "HUD_COLOUR_GOLF_P1": "rgba(240, 240, 240, 255)", + "HUD_COLOUR_GOLF_P2": "rgba(235, 239, 30, 255)", + "HUD_COLOUR_GOLF_P3": "rgba(255, 149, 14, 255)", + "HUD_COLOUR_GOLF_P4": "rgba(246, 60, 161, 255)", + "HUD_COLOUR_WAYPOINTLIGHT": "rgba(210, 166, 249, 255)", + "HUD_COLOUR_WAYPOINTDARK": "rgba(82, 38, 121, 255)", + "HUD_COLOUR_PANEL_LIGHT": "rgba(0, 0, 0, 77)", + "HUD_COLOUR_MICHAEL_DARK": "rgba(72, 103, 116, 255)", + "HUD_COLOUR_FRANKLIN_DARK": "rgba(85, 118, 85, 255)", + "HUD_COLOUR_TREVOR_DARK": "rgba(127, 81, 43, 255)", + "HUD_COLOUR_OBJECTIVE_ROUTE": "rgba(240, 200, 80, 255)", + "HUD_COLOUR_PAUSEMAP_TINT": "rgba(0, 0, 0, 215)", + "HUD_COLOUR_PAUSE_DESELECT": "rgba(100, 100, 100, 127)", + "HUD_COLOUR_PM_WEAPONS_PURCHASABLE": "rgba(45, 110, 185, 255)", + "HUD_COLOUR_PM_WEAPONS_LOCKED": "rgba(240, 240, 240, 191)", + "HUD_COLOUR_END_SCREEN_BG": "rgba(0, 0, 0, 186)", + "HUD_COLOUR_CHOP": "rgba(224, 50, 50, 255)", + "HUD_COLOUR_PAUSEMAP_TINT_HALF": "rgba(0, 0, 0, 215)", + "HUD_COLOUR_NORTH_BLUE_OFFICIAL": "rgba(0, 71, 133, 255)", + "HUD_COLOUR_SCRIPT_VARIABLE_2": "rgba(0, 0, 0, 255)", + "HUD_COLOUR_H": "rgba(33, 118, 37, 255)", + "HUD_COLOUR_HDARK": "rgba(37, 102, 40, 255)", + "HUD_COLOUR_T": "rgba(234, 153, 28, 255)", + "HUD_COLOUR_TDARK": "rgba(225, 140, 8, 255)", + "HUD_COLOUR_HSHARD": "rgba(20, 40, 0, 255)", + "HUD_COLOUR_CONTROLLER_MICHAEL": "rgba(48, 255, 255, 255)", + "HUD_COLOUR_CONTROLLER_FRANKLIN": "rgba(48, 255, 0, 255)", + "HUD_COLOUR_CONTROLLER_TREVOR": "rgba(176, 80, 0, 255)", + "HUD_COLOUR_CONTROLLER_CHOP": "rgba(127, 0, 0, 255)", + "HUD_COLOUR_VIDEO_EDITOR_VIDEO": "rgba(53, 166, 224, 255)", + "HUD_COLOUR_VIDEO_EDITOR_AUDIO": "rgba(162, 79, 157, 255)", + "HUD_COLOUR_VIDEO_EDITOR_TEXT": "rgba(104, 192, 141, 255)", + "HUD_COLOUR_HB_BLUE": "rgba(29, 100, 153, 255)", + "HUD_COLOUR_HB_YELLOW": "rgba(234, 153, 28, 255)", + "HUD_COLOUR_VIDEO_EDITOR_SCORE": "rgba(240, 160, 1, 255)", + "HUD_COLOUR_VIDEO_EDITOR_AUDIO_FADEOUT": "rgba(59, 34, 57, 255)", + "HUD_COLOUR_VIDEO_EDITOR_TEXT_FADEOUT": "rgba(41, 68, 53, 255)", + "HUD_COLOUR_VIDEO_EDITOR_SCORE_FADEOUT": "rgba(82, 58, 10, 255)", + "HUD_COLOUR_HEIST_BACKGROUND": "rgba(37, 102, 40, 186)", + "HUD_COLOUR_VIDEO_EDITOR_AMBIENT": "rgba(240, 200, 80, 255)", + "HUD_COLOUR_VIDEO_EDITOR_AMBIENT_FADEOUT": "rgba(80, 70, 34, 255)", + "HUD_COLOUR_VIDEO_EDITOR_AMBIENT_DARK": "rgba(255, 133, 85, 255)", + "HUD_COLOUR_VIDEO_EDITOR_AMBIENT_LIGHT": "rgba(255, 194, 170, 255)", + "HUD_COLOUR_VIDEO_EDITOR_AMBIENT_MID": "rgba(255, 133, 85, 255)", + "HUD_COLOUR_LOW_FLOW": "rgba(240, 200, 80, 255)", + "HUD_COLOUR_LOW_FLOW_DARK": "rgba(126, 107, 41, 255)", + "HUD_COLOUR_G1": "rgba(247, 159, 123, 255)", + "HUD_COLOUR_G2": "rgba(226, 134, 187, 255)", + "HUD_COLOUR_G3": "rgba(239, 238, 151, 255)", + "HUD_COLOUR_G4": "rgba(113, 169, 175, 255)", + "HUD_COLOUR_G5": "rgba(160, 140, 193, 255)", + "HUD_COLOUR_G6": "rgba(141, 206, 167, 255)", + "HUD_COLOUR_G7": "rgba(181, 214, 234, 255)", + "HUD_COLOUR_G8": "rgba(178, 144, 132, 255)", + "HUD_COLOUR_G9": "rgba(0, 132, 114, 255)", + "HUD_COLOUR_G10": "rgba(216, 85, 117, 255)", + "HUD_COLOUR_G11": "rgba(30, 100, 152, 255)", + "HUD_COLOUR_G12": "rgba(43, 181, 117, 255)", + "HUD_COLOUR_G13": "rgba(233, 141, 79, 255)", + "HUD_COLOUR_G14": "rgba(137, 210, 215, 255)", + "HUD_COLOUR_G15": "rgba(134, 125, 141, 255)", + "HUD_COLOUR_ADVERSARY": "rgba(109, 34, 33, 255)", + "HUD_COLOUR_DEGEN_RED": "rgba(255, 0, 0, 255)", + "HUD_COLOUR_DEGEN_YELLOW": "rgba(255, 255, 0, 255)", + "HUD_COLOUR_DEGEN_GREEN": "rgba(0, 255, 0, 255)", + "HUD_COLOUR_DEGEN_CYAN": "rgba(0, 255, 255, 255)", + "HUD_COLOUR_DEGEN_BLUE": "rgba(0, 0, 255, 255)", + "HUD_COLOUR_DEGEN_MAGENTA": "rgba(255, 0, 255, 255)", + "HUD_COLOUR_STUNT_1": "rgba(38, 136, 234, 255)", + "HUD_COLOUR_STUNT_2": "rgba(224, 50, 50, 255)", + "HUD_COLOUR_SPECIAL_RACE_SERIES": "rgba(154, 178, 54, 255)", + "HUD_COLOUR_SPECIAL_RACE_SERIES_DARK": "rgba(93, 107, 45, 255)", + "HUD_COLOUR_CS": "rgba(206, 169, 13, 255)", + "HUD_COLOUR_CS_DARK": "rgba(103, 84, 6, 255)", + "HUD_COLOUR_TECH_GREEN": "rgba(0, 151, 151, 255)", + "HUD_COLOUR_TECH_GREEN_DARK": "rgba(5, 119, 113, 255)", + "HUD_COLOUR_TECH_RED": "rgba(151, 0, 0, 255)", + "HUD_COLOUR_TECH_GREEN_VERY_DARK": "rgba(0, 40, 40, 255)", + "HUD_COLOUR_PLACEHOLDER_01": "rgba(255, 255, 255, 255)", + "HUD_COLOUR_PLACEHOLDER_02": "rgba(255, 255, 255, 255)", + "HUD_COLOUR_PLACEHOLDER_03": "rgba(255, 255, 255, 255)", + "HUD_COLOUR_PLACEHOLDER_04": "rgba(255, 255, 255, 255)", + "HUD_COLOUR_PLACEHOLDER_05": "rgba(255, 255, 255, 255)", + "HUD_COLOUR_PLACEHOLDER_06": "rgba(255, 255, 255, 255)", + "HUD_COLOUR_PLACEHOLDER_07": "rgba(255, 255, 255, 255)", + "HUD_COLOUR_PLACEHOLDER_08": "rgba(255, 255, 255, 255)", + "HUD_COLOUR_PLACEHOLDER_09": "rgba(255, 255, 255, 255)", + "HUD_COLOUR_PLACEHOLDER_10": "rgba(255, 255, 255, 255)" +} + +GTA_FORMAT_REPLACEMENT_TABLE = [ + [r"~r~", '~HUD_COLOUR_RED~'], + [r"~g~", '~HUD_COLOUR_GREEN~'], + [r"~b~", '~HUD_COLOUR_BLUE~'], + [r"~f~", '~HUD_COLOUR_FRIENDLY~'], + [r"~y~", '~HUD_COLOUR_YELLOW~'], + [r"~c~", '~HUD_COLOUR_MENU_GREY~'], + [r"~t~", '~HUD_COLOUR_MENU_GREY~'], + [r"~o~", '~HUD_COLOUR_ORANGE~'], + [r"~p~", '~HUD_COLOUR_PURPLE~'], + [r"~q~", '~HUD_COLOUR_PINK~'], + [r"~m~", '~HUD_COLOUR_MID_GREY_MP~'], + [r"~l~", '~HUD_COLOUR_BLACK~'], + [r"~d~", '~HUD_COLOUR_BLUEDARK~'], + [r"~s~", '~HUD_COLOUR_GREYLIGHT~'] +] def get_text_from_node(node: xml.dom.minidom.Node): return "".join(t.nodeValue for t in node.childNodes if t.nodeType == t.TEXT_NODE) +def regex_replace_multiple(text: str, replacement_table: list[list[str]]) -> str: + for replacement in replacement_table: + text = re.sub(replacement[0], replacement[1], text) + return text class Validator: """XML Validation @@ -44,6 +309,8 @@ class Validator: found_missing_lang: int = 0 total_strings: int = 0 custom_xml_parser = None + preview_formatting = False + main_doc = None @staticmethod def setup_xml_parser(): @@ -98,7 +365,7 @@ def print_error(error: str, location: list[str], custom_file_cursor: tuple[int] """ Validator.errors += 1 txt = f"[!] {Validator.get_location_string(location, custom_file_cursor=custom_file_cursor)}:\n{error}" - if USE_COLORAMA: + if COLORAMA_INSTALLED: print(f"{colorama.Fore.RED}{txt}{colorama.Fore.RESET}") else: print(txt) @@ -116,7 +383,7 @@ def print_warning(warning: str, location: list[str], custom_file_cursor: tuple[i None """ txt = f"[*] {Validator.get_location_string(location, custom_file_cursor=custom_file_cursor)}:\n{warning}" - if USE_COLORAMA: + if COLORAMA_INSTALLED: print(f"{colorama.Fore.YELLOW}{txt}{colorama.Fore.RESET}") else: print(txt) @@ -143,11 +410,105 @@ def check_unknown_tag(entry: xml.dom.minidom.Element, known_tags: list[str], loc return True Validator.print_error(f"Unknown tag: {repr(entry.tagName)}, expected one of these: {', '.join(known_tags[:Validator.display_limit])}", location, entry.parse_position) return False + + + def setup_html_doc(): + if Validator.preview_formatting: + Validator.main_doc = dominate.document(title="Text formatting preview") + with Validator.main_doc.head: + dominate.tags.style( + """ + html { + background-color: #202327; + } + span, h1, h2, h3 { + color: #ffffff; + } + @font-face { + font-family: 'Chalet'; + src: url('fonts/ChaletLondonNineteenSixty.ttf'); + font-stretch: normal; + } + @font-face { + font-family: 'ChaletComprime'; + src: url('fonts/ChaletComprime_CologneSixty.ttf'); + font-stretch: 1%, 100%; + } + .condensed { + font-family:'ChaletComprime'; + font-size: 2.07vh; + } + .bold { + font-weight: bold; + } + span { + font-family:'Chalet'; + font-weight: lighter; + font-size: 1.725vh; + } + """ + ) + + + def add_formatted_text_to_html(text: str): + text = regex_replace_multiple(text, GTA_FORMAT_REPLACEMENT_TABLE) + GROUP_REGEX = r"~h~|~n~|~bold~|~italic~||<\/C>|~HUD_COLOUR_.+?~|~HC_.+?~|~CC_[0-9]{1,3}_[0-9]{1,3}_[0-9]{1,3}~" + bolded = False + italic = False + color = "rgb(205,205,205)" + condensed = 0 + new_line = False + text_fragments = re.split(GROUP_REGEX, text) + matchedActions = re.findall(GROUP_REGEX, text) + with Validator.main_doc.body: + if text_fragments[0] != "": + dominate.tags.span(text_fragments[0], style=f"color: {color};") + for i, fragment in enumerate(text_fragments[1:]): + formatting = matchedActions[i] + match formatting: + case "~h~" | "~bold~": + bolded = not bolded + case "~italic~": + italic = not italic + case "": + condensed += 1 + case "": + condensed -= 1 + case "~n~": + new_line = not new_line + case _: + HUDColorMatches = re.findall(r"(?<=~)(HUD_COLOUR_.+?)(?=~)|(?<=~)(HC_.+?)(?=~)", formatting) + if HUDColorMatches: + color = GTA_HUD_COLORS[HUDColorMatches[0][0]] + CustomColorMatches = re.findall(r"(?<=~CC_)([0-9]{1,3}_[0-9]{1,3}_[0-9]{1,3})(?=~)", formatting) + if CustomColorMatches: + color = f'rgba(${CustomColorMatches[0].split("_").join(",")})' + classes = [] + if (condensed > 0): + classes.append("condensed") + if bolded: + classes.append("bolded") + style = "" + if italic: + style += "font-style: italic;" + style += f"color: {color};" + with Validator.main_doc.body: + if fragment != "": + with dominate.tags.span(fragment): + if classes: + dominate.tags.attr(cls=' '.join(classes), style=style) + else: + dominate.tags.attr(style=style) + if new_line: + dominate.tags.br() @staticmethod def check_xml_files(): for file in Validator.xml_files: + if DOMINATE_INSTALLED and Validator.preview_formatting: + with Validator.main_doc.body: + dominate.tags.h1(file) try: dom = xml.dom.minidom.parse(file, Validator.custom_xml_parser) root: xml.dom.minidom.Element = dom.documentElement @@ -179,6 +540,9 @@ def check_entries(entry: xml.dom.minidom.Element, path: list[str]): Validator.total_strings -= 1 Validator.used_ids.add(element_found_id) path = [*path, Validator.entry_pretty_print(entry)] + if DOMINATE_INSTALLED and Validator.preview_formatting: + with Validator.main_doc.body: + dominate.tags.h2(element_found_id) found_langs: list[str] = [] lang_attrib = "xml:lang" should_end_with_format = None @@ -206,6 +570,10 @@ def check_entries(entry: xml.dom.minidom.Element, path: list[str]): for string_entry in good_string_entries: text = get_text_from_node(string_entry) current_lang = dict(string_entry.attributes.items()).get(lang_attrib) + if DOMINATE_INSTALLED and Validator.preview_formatting: + with Validator.main_doc.body: + dominate.tags.h3(current_lang) + Validator.add_formatted_text_to_html(text) found_formats = re.findall(FORMAT_REGEX, text) if len(found_formats)>0 and should_end_with_format is not None: found_format = found_formats[-1] @@ -234,13 +602,17 @@ def check_entries(entry: xml.dom.minidom.Element, path: list[str]): if __name__ == '__main__': - if USE_COLORAMA: + if COLORAMA_INSTALLED: colorama.init() parser = argparse.ArgumentParser(description='Validates localization files') parser.add_argument('--show_lang', type=str, help='Show missing language localizations', choices=Validator.supported_langs) + parser.add_argument('--preview_formatting', action='store_true', help='Show formatted localizations as HTML file') parser.add_argument('--display_limit', type=int, default=10, help='Set display limit for missing translations') args = parser.parse_args() Validator.custom_xml_parser = Validator.setup_xml_parser() + if args.preview_formatting and DOMINATE_INSTALLED: + Validator.preview_formatting = True + Validator.setup_html_doc() Validator.display_limit = args.display_limit Validator.show_lang = args.show_lang with open("index.json", "r", encoding="utf-8") as index_file: @@ -254,5 +626,8 @@ def check_entries(entry: xml.dom.minidom.Element, path: list[str]): sys.exit(1) else: print("No errors found") - if USE_COLORAMA: + if Validator.preview_formatting and DOMINATE_INSTALLED: + with open("preview.html", "w", encoding="utf-8") as file: + file.write(Validator.main_doc.render(pretty=False)) + if COLORAMA_INSTALLED: colorama.deinit()