()
| 553 | } |
| 554 | |
| 555 | endOfWord(): Cursor { |
| 556 | if (this.isAtEnd()) { |
| 557 | return this |
| 558 | } |
| 559 | |
| 560 | // Use Intl.Segmenter for proper word boundary detection (including CJK) |
| 561 | const wordBoundaries = this.measuredText.getWordBoundaries() |
| 562 | |
| 563 | // Find the current word boundary we're in |
| 564 | for (const boundary of wordBoundaries) { |
| 565 | if (!boundary.isWordLike) continue |
| 566 | |
| 567 | // If we're inside this word but NOT at the last character |
| 568 | if (this.offset >= boundary.start && this.offset < boundary.end - 1) { |
| 569 | // Move to end of this word (last character position) |
| 570 | return new Cursor(this.measuredText, boundary.end - 1) |
| 571 | } |
| 572 | |
| 573 | // If we're at the last character of a word (end - 1), find the next word's end |
| 574 | if (this.offset === boundary.end - 1) { |
| 575 | // Find next word |
| 576 | for (const nextBoundary of wordBoundaries) { |
| 577 | if (nextBoundary.isWordLike && nextBoundary.start > this.offset) { |
| 578 | return new Cursor(this.measuredText, nextBoundary.end - 1) |
| 579 | } |
| 580 | } |
| 581 | return this |
| 582 | } |
| 583 | } |
| 584 | |
| 585 | // If not in a word, find the next word and go to its end |
| 586 | for (const boundary of wordBoundaries) { |
| 587 | if (boundary.isWordLike && boundary.start > this.offset) { |
| 588 | return new Cursor(this.measuredText, boundary.end - 1) |
| 589 | } |
| 590 | } |
| 591 | |
| 592 | return this |
| 593 | } |
| 594 | |
| 595 | prevWord(): Cursor { |
| 596 | if (this.isAtStart()) { |
nothing calls this directly
no test coverage detected