From af6bc627997fd1b58a201e0bcaddf204f0dfbb68 Mon Sep 17 00:00:00 2001 From: Mr-Neutr0n Date: Wed, 12 Aug 2026 15:52:47 +0530 Subject: [PATCH] fix: repair mojibake arrow directions Signed-off-by: Mr-Neutr0n --- .github/workflows/ci.yml | 3 +++ scripts/fix-mojibake.py | 6 ++++-- scripts/test-fix-mojibake.py | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 scripts/test-fix-mojibake.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65f74cc..084bf01 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,9 @@ jobs: - name: Verify accessible SVG contract run: python3 scripts/test-lint-a11y.py + - name: Verify mojibake repair utility + run: python3 scripts/test-fix-mojibake.py + - name: Run skin linter run: python3 scripts/lint-skin.py --all --baseline diff --git a/scripts/fix-mojibake.py b/scripts/fix-mojibake.py index 856cf17..4334fa7 100644 --- a/scripts/fix-mojibake.py +++ b/scripts/fix-mojibake.py @@ -17,8 +17,10 @@ PAIRS = [ ('…', '…'), # horizontal ellipsis ('•', '•'), # bullet ('→', '→'), # right arrow - ('↑', '←'), # left arrow - ('↑', '↑'), # up arrow (same prefix collision - rare) + # CP1252 leaves byte 0x90 undefined, so spell the left-arrow corruption + # with a Unicode escape instead of embedding an invisible control character. + ('\u00e2\u2020\u0090', '←'), # left arrow + ('↑', '↑'), # up arrow ('↓', '↓'), # down arrow ('≤', '≤'), # less-than-or-equal ('≥', '≥'), # greater-than-or-equal diff --git a/scripts/test-fix-mojibake.py b/scripts/test-fix-mojibake.py new file mode 100644 index 0000000..da4940e --- /dev/null +++ b/scripts/test-fix-mojibake.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +"""Regression tests for the mojibake repair utility.""" + +from __future__ import annotations + +import subprocess +import sys +import tempfile +from pathlib import Path + + +ROOT = Path(__file__).resolve().parent.parent +SCRIPT = ROOT / "scripts" / "fix-mojibake.py" + + +def main() -> int: + # These are the strings produced when UTF-8 arrow bytes are decoded as + # Windows-1252. Byte 0x90 is undefined in CP1252, hence the explicit escape. + source = "right →, left \u00e2\u2020\u0090, up ↑, down ↓\n" + expected = "right →, left ←, up ↑, down ↓\n" + with tempfile.TemporaryDirectory(prefix="diagram-design-mojibake-") as directory: + path = Path(directory) / "fixture.md" + path.write_text(source, encoding="utf-8") + result = subprocess.run( + [sys.executable, str(SCRIPT), str(path)], + capture_output=True, + text=True, + check=False, + ) + if result.returncode != 0: + raise AssertionError(f"repair failed: {result.stdout}{result.stderr}") + actual = path.read_text(encoding="utf-8") + if actual != expected: + raise AssertionError(f"expected {expected!r}, got {actual!r}") + print("PASS: mojibake arrow sequences repair to the intended directions") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())