Notes › Tech Notes › Click HTTPServer Through All 7 Modes and 0 of the 49 Round Trips Give the Name Back

Click HTTPServer Through All 7 Modes and 0 of the 49 Round Trips Give the Name Back

Clicking HTTPServer through all 7 modes on the case converter gives 49 pairs of round trips: 441 measured runs returned the original string only 36 times, and the three inputs with interior capitals never came back. Word splitting knows just two boundaries, and 31 capital letters are erased on the way.

How one class name lost four capitals

The identifier HTTPServer left this page as httpserver in the underscore style, and one more click on PascalCase produced Httpserver. Four capital letters were gone: a run of consecutive capitals never grows back after an underscore.

To measure how far that reaches I laid the 7 modes out as a full matrix: seven styles by seven styles gives 49 pairs, and running nine inputs through every pair gives 441 round trips. Only 36 returned the input untouched, and HTTPServer, myVar2Name and iOS_App-Name finished at 0 out of 49. Case switching looks reversible, but a hidden splitting step cuts the string apart first, and a shape that does not survive the cut cannot be rebuilt. Every figure below comes from pulling the conversion function out of the template and running it input by input.

The splitting step sees only two kinds of boundary

Every input passes three prep steps: trim() strips the outer whitespace, [-_]+ turns a whole run of underscores or hyphens into one space, a space is inserted wherever an ASCII lowercase letter sits in front of an ASCII uppercase letter, and the result is split on /\s+/. Those are the only boundaries the splitter can see, so a name matching neither stays one piece.

InputTokensWhere it stops
HTTPServer1no boundary between consecutive capitals
HTTPRequestHandler2one boundary only, at tH
myVar2Name22N is a digit followed by a capital
API_KEY_V23two _ characters, one space each
iOS_App-Name4two symbol runs plus one boundary at iO

Dots are not boundaries and neither are accented capitals, so a..b and ΩK stay whole, while a tab, a newline and a U+3000 fullwidth space all count as whitespace and cut.

The step that erases capitals inside a token

Once the words are cut, lines 50 to 54 of the Case Converter page fix the case of each token's first character and then run toLowerCase() over everything else. The buttons advertise Title Case and camelCase; the comment in the source never mentions that remainder. Out of 24 measured inputs, 9 carry a capital inside a token and between them 31 capitals are erased.

ABCDEFGHIJ 9 MAX_SIZE 5 HTTPServer 4 API_KEY_V2 4 HTTPRequestHandler 4 iOSAppName 2

Figure 1. Capital letters erased per input, bar length proportional to the count.

ABCDEFGHIJ becomes Abcdefghij and loses 9 capitals at once, while myVar2Name loses one and still cannot return. The title branch takes an extra cut: iPhone splits into 2 tokens, becomes I Phone and gains a space; userID comes out as User Id. Two kinds of damage are easy to confuse here, the capital inside a token and the boundary that snake and kebab overwrite.

Only 36 of the 49 pairs come back unchanged

A round trip means converting once under mode a, then that result once under mode b, and still holding the original string. Nine inputs across the 49 pairs is 441 attempts, and identity shows up 36 times.

user_name 10 user-name 10 userName 5 UserName 5 user name 3 API_KEY_V2 3 HTTPServer 0 myVar2Name 0 iOS_App-Name 0

Figure 2. Pairs out of 49 that restore each input exactly.

Lowercase sources are the forgiving case: the top two rows of the figure each clear 10 pairs. API_KEY_V2 keeps 3, and only because the second leg ends in upper. Run five spellings of one identifier across all 49 pairs and you get 245 trips holding 33 identities. Read it by pair instead of by input and 20 of the 49 never return anything: once the second leg is upper or title the name cannot come back, because the first leg has already flattened the capitals it would need. Only 2 pairs score on three of the five spellings.

Pressing the same mode twice is not always a no-op

Applying one mode twice should be invisible. Across 24 inputs and 7 modes there are 168 double conversions: 9 of them genuinely change the string a second time, and 3 more are thrown away by the empty input guard. Stability then splits by mode. upper, lower, snake and kebab hold all 24 of 24, title holds 23 of 24, camel holds 20 of 24 and pascal only 17 of 24. iPhone on pascal gives IPhone and a second click gives Iphone; the worse case is line1Line2Line3, where the second pass finds no lowercase letter sitting in front of a capital, so nothing is left to split and the identifier collapses into line1line2line3. So a name already in the target shape is not safe to convert twice.

Output length follows a formula, with 3 exceptions

Prediction is easy from the tokens alone: add up the character counts of every token, then add n_tok - 1, because title, snake and kebab insert one separator each while camel and pascal add nothing. Testing 24 inputs against 5 modes gives 120 predictions and 117 of them hit. All 3 misses sit on one input, İstanbul: its first character is U+0130, and lowercasing it yields an i plus a combining dot above, U+0307, adding one code unit to the string. camel, snake and kebab stretch from 8 units to 9, while title and pascal, which pass the first character through charAt(0).toUpperCase(), keep it at 8.

upper and lower never reach the splitter

Lines 48 and 49 write straight over the raw input, with no trimming and no tokenising. Feed in ' hello world ', 17 bytes with two spaces at each end and three in the middle, and upper still returns 17 bytes, inner run intact. camel and pascal return 10 bytes and title, snake and kebab return 11, because those split and collapse every gap into one separator. One 3 byte U+3000 space behaves the same way: it becomes an ASCII space under title, snake and kebab, which grows the output to 19 bytes, and disappears under camel and pascal, leaving 18.

The guard catches six empty shapes and misses one

The entry test is the single line if (!text.trim()). An empty string, three spaces, two tabs, a lone newline, a byte order mark and a fullwidth space, six categories in all, are judged empty: the page shows only its enter some text warning, none of the three lines that write the output run, and neither the old value in the output box nor the display:none state of the panels changes. A sentinel such as <<UNSET>> left in the box beforehand is still sitting there afterwards. A pure symbol run such as ---___--- slips past that guard, though: it is not empty, so it splits into 2 empty tokens and camel and pascal hand back a zero byte result, and copying that result into the input triggers the guard three times again.

A leading empty token, and one pass per paste

If the first character is a - or a _ the split leaves an empty token at the front, so the i === 0 test on line 51 fires against an empty piece instead of the real word. The visible consequence is that _private_var converted to camel comes back as PrivateVar, a PascalCase name sitting in the camelCase slot, and -_-_a reduces to nothing but A.

The template application/index/view/tools/case-convert.html is 67 lines and 3254 bytes long, with one input box, zero loops inside the conversion function, no notion of multiple records and no length ceiling: 200000 characters convert in 11 ms and split into 40001 tokens in that same pass. Which style a team should pick is not this measurement's question; the earlier article on choosing a naming convention for case conversion argues that side. This one only measures what the converter throws away.

Frequently asked questions

Q: Why is HTTPServer not itself after an underscore round trip?

Spaces are inserted only where an ASCII lowercase letter is followed by an ASCII uppercase one, so HTTPServer survives as 1 token, snake case lowercases the whole thing to httpserver, and the capitals are gone then, not merely hidden. A later click on pascal can then only produce Httpserver. For inputs of this shape, not one of the 49 pairs is identical.

Q: How do I keep the capitals of an acronym?

The converter has no concept of an acronym, so nothing can be protected from outside: write the name in a shape the splitter can cut, or add the capitals back by hand. HTTPRequestHandler shows the limit: only tH gives it a boundary, the four capitals in front of it stay glued to their neighbour, and they are erased in the same pass as everything else.

Q: Can I paste a whole multiline block at once?

Yes, the entire block is processed in one pass, which is how 200000 characters turn into 40001 tokens in 11 ms. Line breaks are just whitespace to the splitter, so camel and pascal eat every one of them and a 500 line paste returns as a single line. Only upper and lower keep the line count intact.

📎 Related articles

I Tested 16 Switch Combinations of an HTML Tag Stripper: It Reports 19 Tags but Deletes 148 Characters 2026-10-30 Linked Images Vanish When SVG Turns to PNG: A 594 Byte File Shows 3 Pictures in Preview and 1 in the Export 2026-10-30 Handing a Base64 string to someone else: 4 edits tried, 3 of them throw an error 2026-10-30 App Store Screenshots Export at 1242×2688: 8 Canvas Presets, Noise at 24.83 Times the Size, and a Phone Frame Cropped 134.93 px by Default 2026-10-30 16 Keys In, 4 Columns Out: How json-to-excel Builds CSV Headers 2026-10-30