#!/usr/bin/env python3 """Read entities.json (WHATWG HTML named character references) and generate WingEntities.cpp with a lookup table of { "name", codepoint } rows. Rules: - Only entries whose key ends with ';' (skip legacy semicolon-less forms). - Only entries with exactly one codepoint. - Codepoint must be <= 0xFFFF (Unreal uses 16-bit TCHAR). """ import json, os script_dir = os.path.dirname(os.path.abspath(__file__)) project_dir = os.path.dirname(script_dir) input_path = os.path.join(project_dir, "entities.json") output_path = os.path.join(project_dir, "Plugins", "UEWingman", "Source", "UEWingman", "Private", "WingEntities.cpp") with open(input_path) as f: data = json.load(f) rows = [] for key, val in sorted(data.items()): if not key.endswith(";"): continue cps = val["codepoints"] if len(cps) != 1: continue cp = cps[0] if cp > 0xFFFF: continue # Strip leading '&' and trailing ';' name = key[1:-1] rows.append((name, cp)) with open(output_path, "w") as f: f.write("// Auto-generated by tools/gen-entities.py — do not edit by hand.\n") f.write("// Source: WHATWG HTML named character references (entities.json)\n\n") f.write('#include "WingTokenizer.h"\n\n\n') f.write("WingEntityList::WingEntityList(std::initializer_list Data)\n") f.write("{\n") f.write("\tfor (const Raw& Entry : Data)\n") f.write("\t{\n") f.write('\t\tFString XName((const ANSICHAR*)Entry.Name);\n') f.write("\t\tCharToName.Add(Entry.Codepoint, XName);\n") f.write("\t\tNameToChar.Add(XName, Entry.Codepoint);\n") f.write("\t}\n") f.write("}\n\n") f.write("WingEntityList WingEntityList::TheList({\n") for name, cp in rows: f.write(f'\t{{ "{name}", {cp} }},\n') f.write("});\n") print(f"Generated {len(rows)} entities -> {output_path}")