Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions js/.changeset/calm-terminals-align.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'command-stream': patch
---

Render terminal SVG text at its visible cell-grid position and width without
stretching glyphs across leading or trailing row padding.
16 changes: 15 additions & 1 deletion js/src/terminal-artifacts.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ const cellStyle = (cell, options) => {
const sameStyle = (left, right) =>
Object.keys(left).every((key) => left[key] === right[key]);

const isBlankCell = (cell) => (cell.chars || ' ').trim() === '';

const coalesceRow = (cells, options) => {
const runs = [];
for (let column = 0; column < cells.length; ) {
Expand All @@ -161,13 +163,19 @@ const coalesceRow = (cells, options) => {
column += 1;
continue;
}
if (isBlankCell(cell)) {
column += Math.max(cell.width, 1);
continue;
}
const style = cellStyle(cell, options);
const run = {
column,
width: Math.max(cell.width, 1),
text: cell.chars || ' ',
text: cell.chars,
style,
};
let visibleTextLength = run.text.length;
let visibleWidth = run.width;
column += Math.max(cell.width, 1);
while (column < cells.length) {
const next = cells[column];
Expand All @@ -182,7 +190,13 @@ const coalesceRow = (cells, options) => {
run.text += next.chars || ' ';
run.width += Math.max(next.width, 1);
column += Math.max(next.width, 1);
if (!isBlankCell(next)) {
visibleTextLength = run.text.length;
visibleWidth = run.width;
}
}
run.text = run.text.slice(0, visibleTextLength);
run.width = visibleWidth;
runs.push(run);
}
return runs;
Expand Down
30 changes: 30 additions & 0 deletions js/tests/terminal-capture.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,36 @@ describe('PTY terminal capture', () => {
expect(duration).toBeLessThan(0.5);
});

test('measures visible glyphs without stretching terminal row padding', async () => {
const artifactDirectory = await mkdtemp(
join(tmpdir(), 'command-stream-tui-padding-')
);
temporaryDirectories.push(artifactDirectory);

await captureTerminal({
file: process.execPath,
args: ['-e', "process.stdout.write('\\u001b[3Gok 表')"],
cols: 12,
rows: 2,
artifactDirectory,
artifactOptions: {
cellWidth: 10,
cellHeight: 20,
padding: 0,
},
});

const snapshot = await readFile(
join(artifactDirectory, 'snapshot.svg'),
'utf8'
);
expect(snapshot).toMatch(
/<text x="20" [^>]*textLength="50"[^>]*>ok 表<\/text>/
);
expect(snapshot).not.toMatch(/<text [^>]*>[ \t]/);
expect(snapshot).not.toMatch(/[ \t]<\/text>/);
});

test('unrolls scrolled-off lines in order and exactly once', async () => {
const capture = await captureTerminal({
file: process.execPath,
Expand Down
Loading