Skip to content

Case-map an astral first letter in ToCamelCase and the first-char helpers - #76

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/astral-first-char
Sep 26, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/astral-first-char

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #74

What was wrong

ToLowercaseFirstChar and ToUppercaseFirstChar case-mapped input[0]. For a letter outside the Basic Multilingual Plane (e.g. Deseret 𐐀 U+10400 ↔ 𐐨 U+10428), input[0] is only the high surrogate, so the letter came back unchanged. ToCamelCase goes through ToLowercaseFirstChar, so "𐐀abc".ToCamelCase() returned 𐐀abc, the same as ToPascalCase. #70 had already fixed this for every other conversion.

Change

  • Added a private MapFirstCodePoint helper. It takes the first code point (via the existing CodePointLength), maps it, and appends the rest. Both first-char helpers now use it, which also replaces their duplicated #if NETSTANDARD2_0 branches.
  • Added the four tests from the issue next to the existing astral-letter tests from Letters outside the BMP are silently deleted by every case conversion #70. The all-caps-word test also asserts the BMP equivalent ("XX foo" → "xxFoo").

Verification

  • dotnet test: 38/38 pass.
  • With the source change reverted, the four new tests fail and the other 34 pass.
  • dotnet build CaseConverter/CaseConverter.csproj succeeds for every target framework, including netstandard2.0, with no warnings.

🤖 Generated with Claude Code

https://claude.ai/code/session_018AEYBNCRr6chFLiZDv1MVj


Generated by Claude Code

…pers

ToLowercaseFirstChar and ToUppercaseFirstChar case-mapped input[0], which
for a letter outside the Basic Multilingual Plane is only the high
surrogate, so the letter came back unchanged. ToCamelCase goes through
ToLowercaseFirstChar and inherited this. Map the first code point instead,
using the CodePointLength helper the other conversions already rely on.

Fixes #74

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

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

Development

Successfully merging this pull request may close these issues.

ToCamelCase, ToLowercaseFirstChar and ToUppercaseFirstChar leave a first letter outside the BMP unchanged

2 participants