Skip to content

fix(sanitize): keep the joiners that hold emoji and words together - #349

Merged
chigwell merged 1 commit into
chigwell:mainfrom
axisrow:fix/keep-joiners
Oct 21, 2026
Merged

chigwell merged 1 commit into
chigwell:mainfrom
axisrow:fix/keep-joiners

Conversation

@axisrow

@axisrow axisrow commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

Summary

The invisible-character stripping in sanitize_user_content removes U+200C (ZWNJ) and U+200D (ZWJ) unconditionally (outside preserve_emoji), which mangles two legitimate uses:

  • a ZWJ between two emoji parts — family, flags, profession and skin-tone sequences are single composite emoji built from ZWJ-joined symbols; stripping it splits them into unrelated emoji ("👨‍👩‍👧" → "👨👩👧"),
  • a ZWNJ between letters of a joining script — in Arabic/Persian and the Indic blocks (including their presentation forms), ZWNJ is spelling, not decoration: "نمی‌روم" becomes "نمیروم".

The strip pass now keeps a ZWJ only when both neighbours are emoji parts (So symbols, VS16, skin-tone modifiers) and a ZWNJ only when both neighbours are letters of a ZWNJ-using script; everywhere else — e.g. between Latin letters, where a joiner can split a word to hide it — they are stripped as before. The separate _INVISIBLE_CHARS substitution is folded into the same single pass. With preserve_emoji, ZWJ retention is unchanged.

Testing

  • tests/test_sanitize.py covers composite emoji, Persian ZWNJ spelling, and the hostile case (joiners inside Latin words still stripped).
  • Full suite: 1413 passed.

🤖 Generated with Claude Code

sanitize_user_content stripped every U+200D and U+200C, so list_messages, names and titles returned 👨👩👧👦 instead of 👨‍👩‍👧‍👦, 🏳️🌈 for the pride flag, and Persian/Hindi words without their joiners. Keep a ZWJ between two emoji parts and a ZWJ/ZWNJ between two letters of a joining script (Arabic and Indic blocks). Joiners anywhere else, such as between Latin letters or at the edges, are still stripped, as are all other invisible characters.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018Xun6C4mXUAKbVSmiEEh79
@chigwell
chigwell merged commit ef96c5a into chigwell:main Oct 21, 2026
4 checks passed
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.

3 participants