Summary
When text contains Hangul Compatibility Jamo (U+3130–U+318F), the engine breaks lines too early compared to Chrome and Safari, producing incorrect line counts and wrong height calculations.
Why this matters for Korean users
Hangul Compatibility Jamo are not an edge case. They are the everyday standalone consonants and vowels Korean speakers type constantly in digital communication:
| Expression |
Meaning |
Unicode |
| ㅋㅋㅋ |
laughter ("lol") |
U+314B |
| ㅠㅠ |
crying / sad |
U+3160 |
| ㄹㅇ |
"literally" / "for real" |
U+3139 U+3147 |
| ㄷㄷ |
shivering / scary |
U+3137 |
| ㅇㅋ |
okay |
U+3147 U+314B |
| ㄴㄴ |
no / nope |
U+3134 |
These expressions appear in virtually every Korean chat conversation. Any app targeting Korean users (messaging, social feeds, comment sections, editors) will encounter this constantly.
An incorrect line count means wrong height calculations, which breaks virtual scroll positioning, chat bubble sizing, and cursor placement.
Reproduction
Case 1 — wrong line count (most severe)
font: "20px serif"
width: 200px
text: "ㅋㅋㅋ 진짜 웃기다 ㅋㅋㅋ 진짜로"
pretext: 4 lines ← wrong
browser: 3 lines ✓
mismatch: engine breaks at "웃기다" | browser fits "웃기다 ㅋㅋ" on the same line
Case 2 — wrong line count
font: "20px serif"
width: 150px
text: "이거 ㄹㅇ임 ㄹㅇ 아니면 뭐야"
pretext: 5 lines ← wrong
browser: 4 lines ✓
Case 3 — wrong break position (same line count, different split)
font: "20px serif"
width: 200px
text: "ㄱㄴㄷ 호환 자모 ㄱㄴㄷ 호환 자모 ㄱㄴㄷ"
pretext: line 3 ends at "호환 자모" ← wrong
browser: line 3 ends at "호환 자모 ㄱ" ✓
Reproduced in: Chrome ✓ Safari ✓
Note: the bug is width-sensitive — all Hangul Compatibility Jamo are potentially affected, but failures surface at different widths per character.
Root cause
isCJKCodePoint() in src/analysis.ts includes Hangul syllables (U+AC00–U+D7AF) but is missing Hangul Compatibility Jamo (U+3130–U+318F).
Without CJK classification, these characters are treated as atomic (non-splittable) segments. The line-breaker cannot split ㅋㅋㅋ at grapheme boundaries, so the entire run wraps to the next line when it doesn't fit — while browsers split it character by character.
Fix
Add one range to isCJKCodePoint() in src/analysis.ts:
+ (codePoint >= 0x3130 && codePoint <= 0x318F) || // Hangul Compatibility Jamo (ㄱ-ㅣ)
(codePoint >= 0xAC00 && codePoint <= 0xD7AF) ||
A PR with this fix and a dedicated oracle checker (scripts/korean-check.ts, 19 test cases, all passing on Chrome and Safari) has already been submitted: #141
Summary
When text contains Hangul Compatibility Jamo (U+3130–U+318F), the engine breaks lines too early compared to Chrome and Safari, producing incorrect line counts and wrong height calculations.
Why this matters for Korean users
Hangul Compatibility Jamo are not an edge case. They are the everyday standalone consonants and vowels Korean speakers type constantly in digital communication:
These expressions appear in virtually every Korean chat conversation. Any app targeting Korean users (messaging, social feeds, comment sections, editors) will encounter this constantly.
An incorrect line count means wrong height calculations, which breaks virtual scroll positioning, chat bubble sizing, and cursor placement.
Reproduction
Case 1 — wrong line count (most severe)
Case 2 — wrong line count
Case 3 — wrong break position (same line count, different split)
Reproduced in: Chrome ✓ Safari ✓
Note: the bug is width-sensitive — all Hangul Compatibility Jamo are potentially affected, but failures surface at different widths per character.
Root cause
isCJKCodePoint()insrc/analysis.tsincludes Hangul syllables (U+AC00–U+D7AF) but is missing Hangul Compatibility Jamo (U+3130–U+318F).Without CJK classification, these characters are treated as atomic (non-splittable) segments. The line-breaker cannot split
ㅋㅋㅋat grapheme boundaries, so the entire run wraps to the next line when it doesn't fit — while browsers split it character by character.Fix
Add one range to
isCJKCodePoint()insrc/analysis.ts:+ (codePoint >= 0x3130 && codePoint <= 0x318F) || // Hangul Compatibility Jamo (ㄱ-ㅣ) (codePoint >= 0xAC00 && codePoint <= 0xD7AF) ||A PR with this fix and a dedicated oracle checker (
scripts/korean-check.ts, 19 test cases, all passing on Chrome and Safari) has already been submitted: #141