fix(tags): preserve acronym casing in tag normalization (DC, NSFW)
normalize_tag_name now only capitalizes the first letter of each word and leaves the rest of the word untouched (was lowercasing the tail, which turned DC→Dc / NSFW→Nsfw). This matches ml/tag_name._title_word, so a Camie-suggested tag keeps the exact casing the suggestion UI showed when it round-trips through POST /api/tags on Accept — addressing "auto-suggested tags must obey capitalization" and "don't mangle acronyms" in one rule. Trade-off (operator-chosen): all-caps input no longer folds to Title Case, so case-variant merging in #714 still folds the dominant lowercase-vs-Title case but leaves all-caps stylizations distinct (protecting acronyms wins). Tests updated + a new test documenting acronym preservation / non-folding. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,15 +17,19 @@ log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def normalize_tag_name(name: str) -> str:
|
||||
"""Canonical tag form (#701): collapse whitespace + Title Case.
|
||||
"""Canonical tag form (#701): collapse whitespace + capitalize the first
|
||||
letter of each word, PRESERVING the rest of the word.
|
||||
|
||||
Per-word capitalize (NOT str.title(), which mangles apostrophes:
|
||||
don't → Don'T). Lowercasing the word tail also folds ALL-CAPS input
|
||||
(HATSUNE MIKU → Hatsune Miku); acronym casing is sacrificed, an accepted
|
||||
Title-Case trade-off (operator-chosen 2026-06-06).
|
||||
don't → Don'T). The word tail is left untouched so acronyms survive
|
||||
(DC stays DC, NSFW stays NSFW) — operator-revised 2026-06-06: protecting
|
||||
acronyms matters more than folding ALL-CAPS input. This MATCHES
|
||||
ml/tag_name._title_word, so a tag suggested by the Camie tagger keeps the
|
||||
exact casing the suggestion UI showed when it round-trips through the
|
||||
create endpoint on Accept.
|
||||
"""
|
||||
return " ".join(
|
||||
w[:1].upper() + w[1:].lower() for w in (name or "").split()
|
||||
w[:1].upper() + w[1:] for w in (name or "").split()
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user