(line: string, width: number)
| 743 | } |
| 744 | |
| 745 | function wrapSingleLine(line: string, width: number): string[] { |
| 746 | if (!line) { |
| 747 | return [""]; |
| 748 | } |
| 749 | |
| 750 | const visibleLength = visibleWidth(line); |
| 751 | if (visibleLength <= width) { |
| 752 | return [line]; |
| 753 | } |
| 754 | |
| 755 | const wrapped: string[] = []; |
| 756 | const tracker = new AnsiCodeTracker(); |
| 757 | const tokens = splitIntoTokensWithAnsi(line); |
| 758 | |
| 759 | let currentLine = ""; |
| 760 | let currentVisibleLength = 0; |
| 761 | |
| 762 | for (const token of tokens) { |
| 763 | const tokenVisibleLength = visibleWidth(token); |
| 764 | const isWhitespace = token.trim() === ""; |
| 765 | |
| 766 | // Token itself is too long - break it character by character |
| 767 | if (tokenVisibleLength > width && !isWhitespace) { |
| 768 | if (currentLine) { |
| 769 | // Add specific reset for underline only (preserves background) |
| 770 | const lineEndReset = tracker.getLineEndReset(); |
| 771 | if (lineEndReset) { |
| 772 | currentLine += lineEndReset; |
| 773 | } |
| 774 | wrapped.push(currentLine); |
| 775 | currentLine = ""; |
| 776 | currentVisibleLength = 0; |
| 777 | } |
| 778 | |
| 779 | // Break long token - breakLongWord handles its own resets |
| 780 | const broken = breakLongWord(token, width, tracker); |
| 781 | for (let i = 0; i < broken.length - 1; i++) { |
| 782 | wrapped.push(broken[i]!); |
| 783 | } |
| 784 | currentLine = broken[broken.length - 1]!; |
| 785 | currentVisibleLength = visibleWidth(currentLine); |
| 786 | continue; |
| 787 | } |
| 788 | |
| 789 | // Check if adding this token would exceed width |
| 790 | const totalNeeded = currentVisibleLength + tokenVisibleLength; |
| 791 | |
| 792 | if (totalNeeded > width && currentVisibleLength > 0) { |
| 793 | // Trim trailing whitespace, then add underline reset (not full reset, to preserve background) |
| 794 | let lineToWrap = currentLine.trimEnd(); |
| 795 | const lineEndReset = tracker.getLineEndReset(); |
| 796 | if (lineEndReset) { |
| 797 | lineToWrap += lineEndReset; |
| 798 | } |
| 799 | wrapped.push(lineToWrap); |
| 800 | if (isWhitespace) { |
| 801 | // Don't start new line with whitespace |
| 802 | currentLine = tracker.getActiveCodes(); |
no test coverage detected