Skip to content

Normalize feature names by removing invisible characters only - #1033

Merged
jnunemaker merged 1 commit into
mainfrom
normalize-invisible-chars-only
Jul 24, 2026
Merged

Normalize feature names by removing invisible characters only#1033
jnunemaker merged 1 commit into
mainfrom
normalize-invisible-chars-only

Conversation

@jnunemaker

Copy link
Copy Markdown
Collaborator

Follow-up to #1027 (thanks @koddsson for the report and fix!).

That PR fixed the real problem — pasting a feature name with an invisible character (zero-width space, word joiner, etc.) creates a flag that looks identical in the UI but never matches the name in code. However, transliterating to ASCII had two side effects:

  • Silent renames of visible characters: creating café in the UI produced a cafe flag, which no longer matches code checking Flipper.enabled?(:café) — the same mismatch bug the PR was fixing, just with visible characters.
  • Non-latin names rejected: 新機能 (Japanese, Cyrillic, Hebrew, etc.) normalized to empty string and hit the invalid-name error, so those names could no longer be created via the UI at all.

This changes the normalization to remove only what you can't see, leaving every visible character untouched:

  • Strips unicode format and control characters (\p{Cf} / \p{Cc}: zero-width spaces, joiners, BOM, soft hyphens)
  • Trims unicode whitespace from both ends (non-breaking space, ideographic space — which String#strip misses)
  • Scrubs invalid UTF-8 bytes
  • Names that normalize to empty still fall through to the existing invalid-name error

Since dropped characters are invisible, the result always matches what the user intended to type.

The logic now lives in core as Flipper::Typecast.to_feature_name so it can be shared, and is also applied to POST /features in flipper-api, which had the same gap (with the same fallthrough: names that normalize to empty return the existing 422 name_invalid error instead of creating an empty-key feature).

🤖 Generated with Claude Code

Follow-up to #1027, which fixed invisible characters in UI feature names
by transliterating names to ASCII. That approach silently renamed
accented names (café became cafe, no longer matching code that checks
:café) and rejected non-latin names entirely (新機能 normalized to empty).

Instead, remove only invisible format/control characters (zero-width
spaces, joiners, BOM, soft hyphens) and trim unicode whitespace, leaving
all visible characters untouched. The normalization now lives in core as
Flipper::Typecast.to_feature_name and is also applied to feature
creation through the API, which had the same invisible character gap.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jnunemaker
jnunemaker merged commit 8771b71 into main Jul 24, 2026
33 of 46 checks passed
@jnunemaker
jnunemaker deleted the normalize-invisible-chars-only branch July 24, 2026 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant