diff --git a/api/mlos_sort.py b/api/mlos_sort.py index af5b8fe..7797362 100644 --- a/api/mlos_sort.py +++ b/api/mlos_sort.py @@ -227,6 +227,12 @@ def parse_mod_info(text: str, workshop_id: Optional[str] = None) -> Optional[Mod Parse a mod.info file body. Returns None if no `id=` line found. Lines are `key=value`; keys lowercased; list-fields comma-separated. """ + # Strip a leading UTF-8 BOM if present. Some authors save mod.info with + # BOM (notepad.exe default on Windows); without this, the first line's + # `name=` regex misses because the line starts with U+FEFF instead of + # `n`, leaving the mod with an empty display name even though `id=` on + # subsequent lines parses fine. + text = text.lstrip("") fields: Dict[str, object] = {} for raw in text.splitlines(): line = raw.strip() diff --git a/worker/mlos_sort.py b/worker/mlos_sort.py index b5b7d2b..1399526 100644 --- a/worker/mlos_sort.py +++ b/worker/mlos_sort.py @@ -227,6 +227,12 @@ def parse_mod_info(text: str, workshop_id: Optional[str] = None) -> Optional[Mod Parse a mod.info file body. Returns None if no `id=` line found. Lines are `key=value`; keys lowercased; list-fields comma-separated. """ + # Strip a leading UTF-8 BOM if present. Some authors save mod.info with + # BOM (notepad.exe default on Windows); without this, the first line's + # `name=` regex misses because the line starts with U+FEFF instead of + # `n`, leaving the mod with an empty display name even though `id=` on + # subsequent lines parses fine. + text = text.lstrip("") fields: Dict[str, object] = {} for raw in text.splitlines(): line = raw.strip()