From 1a879d48277f41aa7de2488b04f57b2e518ad95b Mon Sep 17 00:00:00 2001 From: Tarik Moussa Date: Thu, 18 Jun 2026 09:17:43 +0200 Subject: [PATCH] feat(quality): clean LaTeX accents/ties + word-boundary truncation in section titles Polish _clean_title for R-F: strip accent/escape macros (backslash-quote o to o, backslash-amp), convert tilde ties to spaces, and truncate at a word boundary so stored section titles read cleanly (mobius invariance, colin de verdiere). Tests added; ruff + mypy clean. Co-Authored-By: Claude Opus 4.8 --- codex/quality.py | 14 +++++++++----- tests/quality/test_quality.py | 13 +++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/codex/quality.py b/codex/quality.py index c2f1b94..7dc21f8 100644 --- a/codex/quality.py +++ b/codex/quality.py @@ -113,14 +113,18 @@ def classify_section(text: str) -> str: def _clean_title(title: str) -> str: """Normalize a LaTeX ``\\section`` title for use as a section label. - Strips LaTeX commands (``\\emph`` …) and ``{}$``, drops leading section - numbering (``3.2 ``), collapses whitespace, lower-cases, and truncates to - 60 chars so the stored ``section`` value is a clean, comparable string. + Strips LaTeX word-commands (``\\emph`` …), accent/escape macros (``\\"o`` → + ``o``, ``\\&``), ``~`` ties and ``{}$``, drops leading section numbering + (``3.2 ``), collapses whitespace, lower-cases, and truncates to 60 chars at a + word boundary so the stored ``section`` value is a clean, comparable string. """ - t = re.sub(r"\\[a-zA-Z]+\*?", " ", title) # LaTeX commands + t = title.replace("~", " ") # LaTeX non-breaking tie → space + t = re.sub(r"\\[a-zA-Z]+\*?", " ", t) # word-commands: \emph, \mathcal … + t = re.sub(r"\\[^a-zA-Z]", "", t) # accent/escape macros: \"o → o, \', \`, \& t = re.sub(r"[{}$]", "", t) # braces / math delimiters t = re.sub(r"^\s*\d+(?:\.\d+)*\.?\s*", "", t) # leading numbering "3.2 " - return " ".join(t.split()).strip().lower()[:60] + t = " ".join(t.split()).strip().lower() + return t[:60].rsplit(" ", 1)[0] if len(t) > 60 else t def section_label(title: str | None, content: str) -> str: diff --git a/tests/quality/test_quality.py b/tests/quality/test_quality.py index 2cfa631..4895c30 100644 --- a/tests/quality/test_quality.py +++ b/tests/quality/test_quality.py @@ -257,6 +257,19 @@ class TestCleanTitle: def test_collapses_and_lowercases(self): assert _clean_title(" Rigidity Results ") == "rigidity results" + def test_strips_accent_macros(self): + assert _clean_title(r"M\"obius Invariance") == "mobius invariance" + + def test_strips_ties_and_accents(self): + assert _clean_title(r"Colin~de~Verdi\`ere") == "colin de verdiere" + + def test_truncates_at_word_boundary(self): + long = "alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu nu omega" + out = _clean_title(long) + assert len(out) <= 60 + assert not out.endswith(" ") + assert long.lower().startswith(out) # whole words from the start, no partial tail + class TestSectionLabel: def test_title_maps_to_controlled_bucket(self):