@@ -91,6 +91,7 @@ export class DomRendererRowFactory {
9191 let oldSpacing = 0 ;
9292 let oldIsInSelection : boolean = false ;
9393 let spacing = 0 ;
94+ let skipJoinedCheckUntilX = 0 ;
9495 const classes : string [ ] = [ ] ;
9596
9697 const hasHover = linkStart !== - 1 && linkEnd !== - 1 ;
@@ -106,29 +107,41 @@ export class DomRendererRowFactory {
106107
107108 // If true, indicates that the current character(s) to draw were joined.
108109 let isJoined = false ;
110+
111+ // Indicates whether this cell is part of a joined range that should be ignored as it cannot
112+ // be rendered entirely, like the selection state differs across the range.
113+ let isValidJoinRange = ( x >= skipJoinedCheckUntilX ) ;
114+
109115 let lastCharX = x ;
110116
111117 // Process any joined character ranges as needed. Because of how the
112118 // ranges are produced, we know that they are valid for the characters
113119 // and attributes of our input.
114120 let cell = this . _workCell ;
115- if ( joinedRanges . length > 0 && x === joinedRanges [ 0 ] [ 0 ] ) {
116- isJoined = true ;
121+ if ( joinedRanges . length > 0 && x === joinedRanges [ 0 ] [ 0 ] && isValidJoinRange ) {
117122 const range = joinedRanges . shift ( ) ! ;
123+ // If the ligature's selection state is not consistent, don't join it. This helps the
124+ // selection render correctly regardless whether they should be joined.
125+ if ( this . _isCellInSelection ( range [ 0 ] , row ) !== this . _isCellInSelection ( range [ 1 ] , row ) ) {
126+ isValidJoinRange = false ;
127+ skipJoinedCheckUntilX = range [ 1 ] ;
128+ } else {
129+ isJoined = true ;
130+
131+ // We already know the exact start and end column of the joined range,
132+ // so we get the string and width representing it directly
133+ cell = new JoinedCellData (
134+ this . _workCell ,
135+ lineData . translateToString ( true , range [ 0 ] , range [ 1 ] ) ,
136+ range [ 1 ] - range [ 0 ]
137+ ) ;
118138
119- // We already know the exact start and end column of the joined range,
120- // so we get the string and width representing it directly
121- cell = new JoinedCellData (
122- this . _workCell ,
123- lineData . translateToString ( true , range [ 0 ] , range [ 1 ] ) ,
124- range [ 1 ] - range [ 0 ]
125- ) ;
126-
127- // Skip over the cells occupied by this range in the loop
128- lastCharX = range [ 1 ] - 1 ;
139+ // Skip over the cells occupied by this range in the loop
140+ lastCharX = range [ 1 ] - 1 ;
129141
130- // Recalculate width
131- width = cell . getWidth ( ) ;
142+ // Recalculate width
143+ width = cell . getWidth ( ) ;
144+ }
132145 }
133146
134147 const isInSelection = this . _isCellInSelection ( x , row ) ;
@@ -178,6 +191,7 @@ export class DomRendererRowFactory {
178191 && ! isCursorCell
179192 && ! isJoined
180193 && ! isDecorated
194+ && isValidJoinRange
181195 ) {
182196 // no span alterations, thus only account chars skipping all code below
183197 if ( cell . isInvisible ( ) ) {
@@ -435,7 +449,7 @@ export class DomRendererRowFactory {
435449 }
436450
437451 // exclude conditions for cell merging - never merge these
438- if ( ! isCursorCell && ! isJoined && ! isDecorated ) {
452+ if ( ! isCursorCell && ! isJoined && ! isDecorated && isValidJoinRange ) {
439453 cellAmount ++ ;
440454 } else {
441455 charElement . textContent = text ;
0 commit comments