( buffer: string, styles: AnsiCode[], stylePool: StylePool, out: ClusteredChar[], )
| 706 | } |
| 707 | |
| 708 | function flushBuffer( |
| 709 | buffer: string, |
| 710 | styles: AnsiCode[], |
| 711 | stylePool: StylePool, |
| 712 | out: ClusteredChar[], |
| 713 | ): void { |
| 714 | // Compute styleId + hyperlink ONCE for the whole style run. |
| 715 | // Every grapheme in this buffer shares the same styles. |
| 716 | // |
| 717 | // Extract and track hyperlinks separately, filter from styles. |
| 718 | // Always check for OSC 8 codes to filter, not just when a URL is |
| 719 | // extracted. The tokenizer treats OSC 8 close codes (empty URL) as |
| 720 | // active styles, so they must be filtered even when no hyperlink |
| 721 | // URL is present. |
| 722 | const hyperlink = extractHyperlinkFromStyles(styles) ?? undefined |
| 723 | const hasOsc8Styles = |
| 724 | hyperlink !== undefined || |
| 725 | styles.some( |
| 726 | s => |
| 727 | s.code.length >= OSC8_PREFIX.length && s.code.startsWith(OSC8_PREFIX), |
| 728 | ) |
| 729 | const filteredStyles = hasOsc8Styles |
| 730 | ? filterOutHyperlinkStyles(styles) |
| 731 | : styles |
| 732 | const styleId = stylePool.intern(filteredStyles) |
| 733 | |
| 734 | for (const { segment: grapheme } of getGraphemeSegmenter().segment(buffer)) { |
| 735 | out.push({ |
| 736 | value: grapheme, |
| 737 | width: stringWidth(grapheme), |
| 738 | styleId, |
| 739 | hyperlink, |
| 740 | }) |
| 741 | } |
| 742 | } |
| 743 | |
| 744 | /** |
| 745 | * Write a single line's characters into the screen buffer. |
no test coverage detected