1
+ import NodeIterator from '../node-iterator'
2
+ import { textNode } from '../node-type'
3
+
1
4
/**
2
5
* @param {HTMLElement | Array | String } target
3
6
* @param {Document } document
@@ -228,21 +231,21 @@ export const createRangeFromCharacterRange = (element, actualStartIndex, actualE
228
231
let startNode , endNode , startOffset , endOffset
229
232
230
233
while ( walker . nextNode ( ) ) {
231
- const textNode = walker . currentNode
232
- const nodeLength = textNode . nodeValue . length
234
+ const node = walker . currentNode
235
+ const nodeLength = node . nodeValue . length
233
236
234
237
if ( currentIndex + nodeLength <= actualStartIndex ) {
235
238
currentIndex += nodeLength
236
239
continue
237
240
}
238
241
239
242
if ( ! startNode ) {
240
- startNode = textNode
243
+ startNode = node
241
244
startOffset = actualStartIndex - currentIndex
242
245
}
243
246
244
247
if ( currentIndex + nodeLength >= actualEndIndex ) {
245
- endNode = textNode
248
+ endNode = node
246
249
endOffset = actualEndIndex - currentIndex
247
250
break
248
251
}
@@ -260,3 +263,87 @@ export const createRangeFromCharacterRange = (element, actualStartIndex, actualE
260
263
}
261
264
}
262
265
266
+ export function findStartExcludingWhitespace ( { root, startContainer, startOffset, whitespacesOnTheLeft} ) {
267
+ const isTextNode = startContainer . nodeType === textNode
268
+ if ( ! isTextNode ) {
269
+ return findStartExcludingWhitespace ( {
270
+ root,
271
+ startContainer : startContainer . childNodes [ startOffset ] ,
272
+ startOffset : 0 ,
273
+ whitespacesOnTheLeft
274
+ } )
275
+ }
276
+
277
+ const offsetAfterWhitespace = startOffset + whitespacesOnTheLeft
278
+ if ( startContainer . length > offsetAfterWhitespace ) {
279
+ return [ startContainer , offsetAfterWhitespace ]
280
+ }
281
+
282
+ // Pass the root so that the iterator can traverse to siblings
283
+ const iterator = new NodeIterator ( root )
284
+ // Set the position to the node which is selected
285
+ iterator . nextNode = startContainer
286
+ // Iterate once to avoid returning self
287
+ iterator . getNextTextNode ( )
288
+
289
+ const container = iterator . getNextTextNode ( )
290
+ if ( ! container ) {
291
+ // No more text nodes - use the end of the last text node
292
+ const previousTextNode = iterator . getPreviousTextNode ( )
293
+ return [ previousTextNode , previousTextNode . length ]
294
+ }
295
+
296
+ return findStartExcludingWhitespace ( {
297
+ root,
298
+ startContainer : container ,
299
+ startOffset : 0 ,
300
+ whitespacesOnTheLeft : offsetAfterWhitespace - startContainer . length
301
+ } )
302
+ }
303
+
304
+ export function findEndExcludingWhitespace ( { root, endContainer, endOffset, whitespacesOnTheRight} ) {
305
+ const isTextNode = endContainer . nodeType === textNode
306
+ if ( ! isTextNode ) {
307
+ const isFirstNode = ! endContainer . childNodes [ endOffset - 1 ]
308
+ const container = isFirstNode
309
+ ? endContainer . childNodes [ endOffset ]
310
+ : endContainer . childNodes [ endOffset - 1 ]
311
+ let offset = 0
312
+ if ( ! isFirstNode ) {
313
+ offset = container . nodeType === textNode
314
+ ? container . length
315
+ : container . childNodes . length
316
+ }
317
+ return findEndExcludingWhitespace ( {
318
+ root,
319
+ endContainer : container ,
320
+ endOffset : offset ,
321
+ whitespacesOnTheRight
322
+ } )
323
+ }
324
+
325
+ const offsetBeforeWhitespace = endOffset - whitespacesOnTheRight
326
+ if ( offsetBeforeWhitespace > 0 ) {
327
+ return [ endContainer , offsetBeforeWhitespace ]
328
+ }
329
+
330
+ // Pass the root so that the iterator can traverse to siblings
331
+ const iterator = new NodeIterator ( root )
332
+ // Set the position to the node which is selected
333
+ iterator . previous = endContainer
334
+ // Iterate once to avoid returning self
335
+ iterator . getPreviousTextNode ( )
336
+
337
+ const container = iterator . getPreviousTextNode ( )
338
+ if ( ! container ) {
339
+ // No more text nodes - use the start of the first text node
340
+ return [ iterator . getNextTextNode ( ) , 0 ]
341
+ }
342
+
343
+ return findEndExcludingWhitespace ( {
344
+ root,
345
+ endContainer : container ,
346
+ endOffset : container . length ,
347
+ whitespacesOnTheRight : whitespacesOnTheRight - endOffset
348
+ } )
349
+ }
0 commit comments