@@ -128,40 +128,45 @@ public void Parse_AllFiveSkinTones_SameCellCount()
128128 [ Fact ]
129129 public void Parse_KeycapSequence_FE0FAndKeycapAreCombiners ( )
130130 {
131- // 1️⃣ = '1'(1 cell) + FE0F(combiner ) + U+20E3(combiner) = 1 cell
131+ // 1️⃣ = '1'(1 cell) + FE0F(VS16 widens to 2 ) + U+20E3(combiner) = 2 cells
132132 var cells = MarkupParser . Parse ( "1\uFE0F \u20E3 " , Color . White , Color . Black ) ;
133133
134- Assert . Single ( cells ) ;
134+ Assert . Equal ( 2 , cells . Count ) ;
135135 Assert . Equal ( new Rune ( '1' ) , cells [ 0 ] . Character ) ;
136136 Assert . Equal ( "\uFE0F \u20E3 " , cells [ 0 ] . Combiners ) ;
137+ Assert . True ( cells [ 1 ] . IsWideContinuation ) ;
137138 }
138139
139140 [ Fact ]
140- public void StripLength_KeycapSequence_Returns1 ( )
141+ public void StripLength_KeycapSequence_Returns2 ( )
141142 {
142- // 1️⃣ = '1'(1) + FE0F(0 ) + U+20E3(0) = 1
143- Assert . Equal ( 1 , MarkupParser . StripLength ( "1\uFE0F \u20E3 " ) ) ;
143+ // 1️⃣ = '1'(1) + FE0F(+1 VS16 widening ) + U+20E3(0) = 2
144+ Assert . Equal ( 2 , MarkupParser . StripLength ( "1\uFE0F \u20E3 " ) ) ;
144145 }
145146
146147 [ Fact ]
147- public void Parse_HashKeycap_SingleCell ( )
148+ public void Parse_HashKeycap_TwoCells ( )
148149 {
150+ // #️⃣ = '#'(1) + FE0F(VS16 widens to 2) + U+20E3(0) = 2 cells
149151 var cells = MarkupParser . Parse ( "#\uFE0F \u20E3 " , Color . White , Color . Black ) ;
150- Assert . Single ( cells ) ;
152+ Assert . Equal ( 2 , cells . Count ) ;
151153 Assert . Equal ( new Rune ( '#' ) , cells [ 0 ] . Character ) ;
154+ Assert . True ( cells [ 1 ] . IsWideContinuation ) ;
152155 }
153156
154157 [ Fact ]
155158 public void Parse_MultipleKeycaps_CorrectCellCount ( )
156159 {
157- // "1️⃣2️⃣" = 1(1 ) + 2(1 ) = 2 cells (FE0F + 20E3 are combiners on each )
160+ // "1️⃣2️⃣" = 1(2 ) + 2(2 ) = 4 cells (VS16 widens each keycap base )
158161 var cells = MarkupParser . Parse (
159162 "1\uFE0F \u20E3 2\uFE0F \u20E3 " ,
160163 Color . White , Color . Black ) ;
161164
162- Assert . Equal ( 2 , cells . Count ) ;
165+ Assert . Equal ( 4 , cells . Count ) ;
163166 Assert . Equal ( new Rune ( '1' ) , cells [ 0 ] . Character ) ;
164- Assert . Equal ( new Rune ( '2' ) , cells [ 1 ] . Character ) ;
167+ Assert . True ( cells [ 1 ] . IsWideContinuation ) ;
168+ Assert . Equal ( new Rune ( '2' ) , cells [ 2 ] . Character ) ;
169+ Assert . True ( cells [ 3 ] . IsWideContinuation ) ;
165170 }
166171
167172 #endregion
@@ -207,14 +212,15 @@ public void Parse_EmojiWithFE0F_AttachesToBaseNotContinuation()
207212 }
208213
209214 [ Fact ]
210- public void Parse_NarrowCharWithFE0F_SingleCellWithCombiner ( )
215+ public void Parse_NarrowCharWithFE0F_WidenedToTwoCells ( )
211216 {
212- // ✈ (U+2708, narrow 1 cell) + FE0F = 1 cell with combiner
217+ // ✈ (U+2708, narrow 1 cell) + FE0F (VS16 widens to 2) = 2 cells
213218 var cells = MarkupParser . Parse ( "\u2708 \uFE0F " , Color . White , Color . Black ) ;
214219
215- Assert . Single ( cells ) ;
220+ Assert . Equal ( 2 , cells . Count ) ;
216221 Assert . Equal ( new Rune ( '\u2708 ' ) , cells [ 0 ] . Character ) ;
217222 Assert . Contains ( "\uFE0F " , cells [ 0 ] . Combiners ) ;
223+ Assert . True ( cells [ 1 ] . IsWideContinuation ) ;
218224 }
219225
220226 [ Fact ]
@@ -456,10 +462,11 @@ public void Parse_KeycapInMarkup_CorrectCells()
456462 // [bold]1️⃣[/] — the literal text path in MarkupParser handles this
457463 var cells = MarkupParser . Parse ( "[bold]1\uFE0F \u20E3 [/]" , Color . White , Color . Black ) ;
458464
459- // '1' is base cell, FE0F and 20E3 are zero-width combiners
460- Assert . Single ( cells ) ;
465+ // '1' is base cell, FE0F widens it (VS16), 20E3 is combiner = 2 cells
466+ Assert . Equal ( 2 , cells . Count ) ;
461467 Assert . Equal ( new Rune ( '1' ) , cells [ 0 ] . Character ) ;
462468 Assert . NotNull ( cells [ 0 ] . Combiners ) ;
469+ Assert . True ( cells [ 1 ] . IsWideContinuation ) ;
463470 }
464471
465472 [ Fact ]
@@ -524,9 +531,9 @@ public void Truncate_EmojiWithFE0F_PreservesTrailingCombiner()
524531 [ Fact ]
525532 public void Truncate_KeycapSequence_PreservesCombiners ( )
526533 {
527- // "1️⃣AB" = 1(1)+FE0F(0 )+20E3(0)+A(1)+B(1) = 3
528- // Truncate to 1 : "1️⃣" (1 + trailing combiners )
529- var result = MarkupParser . Truncate ( "1\uFE0F \u20E3 AB" , 1 ) ;
534+ // "1️⃣AB" = 1(1)+FE0F(+1 VS16 widening )+20E3(0)+A(1)+B(1) = 4
535+ // Truncate to 2 : "1️⃣" (keycap is 2 cols wide with VS16 )
536+ var result = MarkupParser . Truncate ( "1\uFE0F \u20E3 AB" , 2 ) ;
530537
531538 Assert . Equal ( "1\uFE0F \u20E3 " , result ) ;
532539 }
0 commit comments