Skip to content

Keep combining marks and non-ASCII digits in Pascal, Camel, Snake, Kebab and Macro case [patch] - #108

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/80-combining-marks-and-unicode-digits
Oct 6, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/80-combining-marks-and-unicode-digits

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #80

What changed

  • ReplaceNonAlphaNumericWithSpace now keeps combining marks (NonSpacingMark, SpacingCombiningMark, EnclosingMark) and every Unicode decimal digit (char.IsDigit(input, i)). Before, it kept only letters and ASCII 0–9.
  • IsWordBoundary never breaks before a combining mark. It also judges the code point after the marks against the letter they attach to, using the new SkipBackOverCombiningMarks. So "caféBar" still splits before the B.
  • IsWordCharacter, used by the all-caps word normaliser, counts a combining mark as part of its word. "ÉCLAIR" therefore normalises the same way as "éclair".
  • The first-code-point mapping needed no change. Marks have no case, and the marks after the first letter are left where they are.
Input Call Before After
हिन्दी भाषा ToSnakeCase() ह_न_द_भ_ष हिन्दी_भाषा
हिन्दी भाषा ToPascalCase() हनदभष हिन्दीभाषा
éclair (NFD) ToPascalCase() EClair Éclair
café au lait (NFD) ToPascalCase() CafeAuLait CaféAuLait
x١٢٣y ToSnakeCase() x_y x_١٢٣y

Interaction with #107 (#78): the issue's table expects "x١٢٣y".ToPascalCase() to give "X١٢٣Y". The maintainer decided on #78 that a letter after a digit does not start a word, so once #107 merges that output becomes "X١٢٣y". To keep these tests valid either way, the Pascal and Camel cases here use "x١٢٣ y". The two branches merge cleanly with each other (checked with git merge-tree).

Tests

  • CombiningMarksAndNonAsciiDigitsShouldBeKept checks Devanagari, NFD Latin, Arabic-Indic digits and Devanagari digits across Pascal, Camel, Snake, Kebab and Macro.
  • Further tests cover the cased round-trip through Pascal and Camel, a non-ASCII digit after a letter in snake_case, all-caps words that carry a mark, and a capital after a mark.
  • With the source change reverted, 8 of the new test cases fail.
  • The full suite passes on net10.0 (129 tests), and the library builds for every target framework with no warnings.

A caseless script such as Devanagari cannot round-trip through PascalCase, because no capital marks where a word starts. That assertion is therefore limited to cased text.

🤖 Generated with Claude Code

https://claude.ai/code/session_015ef5k7pqkftQmMd6x5w9xM


Generated by Claude Code

…bab and Macro case [patch]

ReplaceNonAlphaNumericWithSpace kept only letters and ASCII digits, so
Devanagari vowel signs and viramas, the accents of NFD Latin text, and
Arabic-Indic or Devanagari digits were replaced with spaces:
"हिन्दी भाषा".ToSnakeCase() gave "ह_न_द_भ_ष".

Combining marks (Mn, Mc, Me) and Unicode decimal digits are now kept.
IsWordBoundary never breaks before a combining mark and judges what
follows against the letter the marks attach to, and the all-caps word
scan treats a mark as part of its word.

Fixes #80

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ef5k7pqkftQmMd6x5w9xM
@sonarqubecloud

sonarqubecloud Bot commented Oct 5, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants