1
+ import { FF_DEV_2480 , isFF } from "./feature-flags" ;
1
2
import { clamp , isDefined } from "./utilities" ;
2
3
3
4
const isTextNode = node => node && node . nodeType === Node . TEXT_NODE ;
@@ -275,11 +276,13 @@ const applyTextGranularity = (selection, granularity) => {
275
276
* @param {HTMLElement } commonContainer
276
277
* @param {HTMLElement } node
277
278
* @param {number } offset
279
+ * @param {string } direction forward, backward, forward-next, backward-next
280
+ * "-next" when we need to skip node if it's a text node
278
281
*/
279
- const textNodeLookup = ( commonContainer , node , offset , direction ) => {
282
+ const textNodeLookup = ( commonContainer , node , offset , direction = "forward" ) => {
280
283
const startNode = node === commonContainer ? node . childNodes [ offset ] : node ;
281
284
282
- if ( isTextNode ( startNode ) ) return startNode ;
285
+ if ( isTextNode ( startNode ) && ! direction . endsWith ( "next" ) ) return startNode ;
283
286
284
287
const walker = commonContainer . ownerDocument . createTreeWalker ( commonContainer , NodeFilter . SHOW_ALL ) ;
285
288
let currentNode = walker . nextNode ( ) ;
@@ -290,7 +293,9 @@ const textNodeLookup = (commonContainer, node, offset, direction) => {
290
293
currentNode = walker . nextNode ( ) ;
291
294
}
292
295
293
- if ( currentNode && direction === "backward" ) return lastTextNode ;
296
+ if ( currentNode && direction . startsWith ( "backward" ) ) return lastTextNode ;
297
+
298
+ if ( direction === "forward-next" ) currentNode = walker . nextNode ( ) ;
294
299
295
300
while ( currentNode ) {
296
301
if ( isTextNode ( currentNode ) ) return currentNode ;
@@ -312,10 +317,27 @@ const fixRange = range => {
312
317
range . setStart ( startContainer , 0 ) ;
313
318
}
314
319
320
+ if ( isFF ( FF_DEV_2480 ) && startContainer . wholeText . length === startOffset ) {
321
+ do {
322
+ startContainer = textNodeLookup ( commonContainer , startContainer , startOffset , "forward-next" ) ;
323
+ } while ( / ^ \s * $ / . test ( startContainer . wholeText ) ) ;
324
+ range . setStart ( startContainer , 0 ) ;
325
+ }
326
+
315
327
if ( ! isTextNode ( endContainer ) ) {
328
+ let isIncluded = false ;
329
+
316
330
endContainer = textNodeLookup ( commonContainer , endContainer , endOffset , "backward" ) ;
317
331
if ( ! endContainer ) return null ;
318
- const isIncluded = ! ! range . toString ( ) . match ( endContainer . wholeText ) ?. length ;
332
+
333
+ if ( isFF ( FF_DEV_2480 ) ) {
334
+ while ( / ^ \s * $ / . test ( endContainer . wholeText ) ) {
335
+ endContainer = textNodeLookup ( commonContainer , endContainer , endOffset , "backward-next" ) ;
336
+ }
337
+ isIncluded = range . toString ( ) . trimEnd ( ) . endsWith ( endContainer . wholeText . trimEnd ( ) ) ;
338
+ } else {
339
+ isIncluded = range . toString ( ) . includes ( endContainer . wholeText ) ;
340
+ }
319
341
320
342
range . setEnd ( endContainer , isIncluded ? endContainer . length : 0 ) ;
321
343
}
0 commit comments