CLAUDE WATERMARK REMOVER · PRACTICAL TEST
Why does Number reject a formatted cleaned amount like 1.234,50?
Our cleaned 1234.5 formats as 1.234,50 under de-DE with two fraction digits, but Number of that display is NaN. formatToParts labels the inserted separators; formatting is a presentation step rather than a reversible parse contract.
Open the Claude text cleaner · Full measured data
Measured inputs and outputs
These are locally constructed test strings, not evidence that Claude inserts these characters. We executed the saved homepage script snapshot with a minimal DOM harness and compared exact strings. The invisible-checkbox state and dash mode appear in each row. The observations below test this page's specific question. Destination observations run independently on the exact input and cleaned strings in the recorded Node runtime. We make no detector-score or statistical-watermark removal claim.
| Fixture and mode | Input string and code points | Output and cleaner status | Observed before / after |
|---|---|---|---|
| Marked amount direct string / keep / invisible true | "1234.5"U+0031 U+0032 U+200B U+0033 U+0034 U+002E U+0035 | "1234.5"Removed 1 invisible character | {"numberLabel":"NaN","finite":false,"display":"NaN","parts":[{"type":"nan","value":"NaN"}],"reparsedLabel":"NaN","exactRoundTrip":true}{"numberLabel":"1234.5","finite":true,"display":"1.234,50","parts":[{"type":"integer","value":"1"},{"type":"group","value":"."},{"type":"integer","value":"234"},{"type":"decimal","value":","},{"type":"fraction","value":"50"}],"reparsedLabel":"NaN","exactRoundTrip":false} |
| Plain amount direct string / keep / invisible true | "1234.5"U+0031 U+0032 U+0033 U+0034 U+002E U+0035 | "1234.5"No selected invisible characters found | {"numberLabel":"1234.5","finite":true,"display":"1.234,50","parts":[{"type":"integer","value":"1"},{"type":"group","value":"."},{"type":"integer","value":"234"},{"type":"decimal","value":","},{"type":"fraction","value":"50"}],"reparsedLabel":"NaN","exactRoundTrip":false}{"numberLabel":"1234.5","finite":true,"display":"1.234,50","parts":[{"type":"integer","value":"1"},{"type":"group","value":"."},{"type":"integer","value":"234"},{"type":"decimal","value":","},{"type":"fraction","value":"50"}],"reparsedLabel":"NaN","exactRoundTrip":false} |
| Precision rounding direct string / keep / invisible true | "1.234"U+0031 U+002E U+0032 U+0033 U+0034 | "1.234"No selected invisible characters found | {"numberLabel":"1.234","finite":true,"display":"1,23","parts":[{"type":"integer","value":"1"},{"type":"decimal","value":","},{"type":"fraction","value":"23"}],"reparsedLabel":"NaN","exactRoundTrip":false}{"numberLabel":"1.234","finite":true,"display":"1,23","parts":[{"type":"integer","value":"1"},{"type":"decimal","value":","},{"type":"fraction","value":"23"}],"reparsedLabel":"NaN","exactRoundTrip":false} |
| Negative amount direct string / keep / invisible true | "-1234.5"U+002D U+0031 U+0032 U+0033 U+0034 U+002E U+0035 | "-1234.5"No selected invisible characters found | {"numberLabel":"-1234.5","finite":true,"display":"-1.234,50","parts":[{"type":"minusSign","value":"-"},{"type":"integer","value":"1"},{"type":"group","value":"."},{"type":"integer","value":"234"},{"type":"decimal","value":","},{"type":"fraction","value":"50"}],"reparsedLabel":"NaN","exactRoundTrip":false}{"numberLabel":"-1234.5","finite":true,"display":"-1.234,50","parts":[{"type":"minusSign","value":"-"},{"type":"integer","value":"1"},{"type":"group","value":"."},{"type":"integer","value":"234"},{"type":"decimal","value":","},{"type":"fraction","value":"50"}],"reparsedLabel":"NaN","exactRoundTrip":false} |
A valid number can become a display that Number cannot read
The marked amount fails Number conversion before deletion. After the selected U+200B is removed, conversion yields the finite value 1234.5. The fixed German formatter then produces a group dot, decimal comma and two fraction digits in 1.234,50. Number on that formatted display returns NaN. The unmarked reference behaves identically without a text edit. Our 1.234 precision control formats as 1,23, showing a rounding change as well as punctuation, and the negative control includes a labeled minus-sign part. Each observation stores the initial numeric label, finiteness, display, parts and reparsed label. These separate fields make it clear that conversion initially succeeds while a later attempt to reuse the display as numeric input fails.
Parts explain generated text without implementing a parser
The observer uses de-DE and fixes both minimum and maximum fraction digits at two. The returned parts label integer, group, decimal, fraction and minus-sign spans in these selected outputs. That is useful provenance for display characters, but the operation does not define a locale parser or recover digits already rounded away. Our earlier currency guide tests whether an option is accepted; this test supplies a valid ordinary decimal formatter and studies what its output can be used for. It does not exercise every locale, alternate numbering systems, currency rounding or formatted-text cleanup. The marked pre-cleanup NaN also compares equal to reparsed NaN under Object.is; that true diagnostic flag is not a valid financial value or a successful finite-number round trip.
Store a numeric representation separately from its presentation
For a destination that displays localized amounts, keep the underlying validated numeric value and the rendered label as separate representations. If user input itself is localized, use that application’s specified parsing and validation policy rather than removing commas or dots blindly. The same punctuation can have different roles under different conventions. Our precision control further shows why accepting a formatted display cannot restore an exact original value after rounding. The downloads preserve the complete parts and runtime locale metadata, allowing a destination-specific rerun. They do not validate money calculations or provide a universal localized-number parser. Review the final storage contract after intentional cleanup, and do not interpret a zero removal count on the original amount as evidence that subsequent display text is safe to feed back to Number.
Reproduce this test
Save reproduce.cjs and tested-app.js in the same folder. Run the command below with Node.js. The harness prints its runtime, script SHA-256 and every measured row. Compare those rows with the original record. Using a newer script or runtime creates a new experiment; retain the version information with your rerun.
node reproduce.cjsReference and next check
ECMA-402 Intl.NumberFormat provides the relevant primary definition. The table and fixture analysis are original measurements. For broader inspection, use our Unicode inspector. Read the scope distinction before interpreting cleanup as a watermark result.