| 63 | } |
| 64 | |
| 65 | private renderFullFrame(frame: Frame): Diff { |
| 66 | const { screen } = frame |
| 67 | const lines: string[] = [] |
| 68 | let currentStyles: AnsiCode[] = [] |
| 69 | let currentHyperlink: Hyperlink = undefined |
| 70 | for (let y = 0; y < screen.height; y++) { |
| 71 | let line = '' |
| 72 | for (let x = 0; x < screen.width; x++) { |
| 73 | const cell = cellAt(screen, x, y) |
| 74 | if (cell && cell.width !== CellWidth.SpacerTail) { |
| 75 | // Handle hyperlink transitions |
| 76 | if (cell.hyperlink !== currentHyperlink) { |
| 77 | if (currentHyperlink !== undefined) { |
| 78 | line += LINK_END |
| 79 | } |
| 80 | if (cell.hyperlink !== undefined) { |
| 81 | line += oscLink(cell.hyperlink) |
| 82 | } |
| 83 | currentHyperlink = cell.hyperlink |
| 84 | } |
| 85 | const cellStyles = this.options.stylePool.get(cell.styleId) |
| 86 | const styleDiff = diffAnsiCodes(currentStyles, cellStyles) |
| 87 | if (styleDiff.length > 0) { |
| 88 | line += ansiCodesToString(styleDiff) |
| 89 | currentStyles = cellStyles |
| 90 | } |
| 91 | line += cell.char |
| 92 | } |
| 93 | } |
| 94 | // Close any open hyperlink before resetting styles |
| 95 | if (currentHyperlink !== undefined) { |
| 96 | line += LINK_END |
| 97 | currentHyperlink = undefined |
| 98 | } |
| 99 | // Reset styles at end of line so trimEnd doesn't leave dangling codes |
| 100 | const resetCodes = diffAnsiCodes(currentStyles, []) |
| 101 | if (resetCodes.length > 0) { |
| 102 | line += ansiCodesToString(resetCodes) |
| 103 | currentStyles = [] |
| 104 | } |
| 105 | lines.push(line.trimEnd()) |
| 106 | } |
| 107 | |
| 108 | if (lines.length === 0) { |
| 109 | return [] |
| 110 | } |
| 111 | return [{ type: 'stdout', content: lines.join('\n') }] |
| 112 | } |
| 113 | |
| 114 | private getRenderOpsForDone(prev: Frame): Diff { |
| 115 | this.state.previousOutput = '' |