fix: apply the review items for #686 at merge

- constants.js:2618 terminalUrlContinuationExtent: trailingColumns now needs a
  one-row first line (first.startRow === first.endRow), so a URL row that
  soft-wraps with a column on its wrapped part no longer glues the next row
  onto that column (`/tmp/report.txtccc/x.html` at 41 columns); master's links
  come back. Negative tests for the extent and the link provider.
- constants.js:2847 terminalCellWrappedPaths: comment reworded to match the
  JSDoc (the exception is a left-column PATH), plus the wrapped-prose case.
- docs/architecture-invariants.md, CLAUDE.md: one clause that a left column of
  wrapped prose (a Description | Path table) also fills the continuation row,
  so the path beside it keeps its per-row fragment links, the safe direction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer committed 2026-10-27 01:23:56 +01:00
1 parent ae3d31407b
commit e93382f2f1
4 files changed
+43 -9

No files matched your search

+24
View File
@@ -241,6 +241,15 @@ const STILL_CONTINUES_ROWS: [string, string, string][] = [
[' Docs: https://example.com/guide?', ' x=1&y=2 more text', 'https://example.com/guide?x=1&y=2'],
[' https://example.com/files/', ' 2026%20Plan.xlsx', 'https://example.com/files/2026%20Plan.xlsx'],
];
// A URL row that soft-wraps at 41 columns with a table column on its wrapped
// part, over an indented row: the column and that row are separate links, never
// one glued `/tmp/report.txtccc/x.html`.
const SOFT_WRAP_COLS = 41;
const SOFT_WRAPPED_URL_ROWS: Row[] = [
{ text: ' Doc https://example.com/aaaaaaaaaaaaaa' },
{ text: 'bbb/ /tmp/report.txt', isWrapped: true },
{ text: ' ccc/x.html' },
];
describe('findTerminalUrls (grammar)', () => {
const { findTerminalUrls } = loadPure();
@@ -439,6 +448,13 @@ describe('terminalUrlContinuationExtent (wrap joining)', () => {
expect(extent).not.toBeNull();
expect(extent!.endRow - extent!.startRow + 1).toBeLessThanOrEqual(5);
});
it('does not continue a URL whose row soft-wraps with a column on the wrapped part', () => {
const buffer = fakeBuffer(SOFT_WRAPPED_URL_ROWS, SOFT_WRAP_COLS);
for (const row of [0, 1, 2]) {
expect(terminalUrlContinuationExtent(buffer, row, SOFT_WRAP_COLS, 12)).toBeNull();
}
});
});
describe('native OSC 8 terminal URLs', () => {
@@ -665,6 +681,14 @@ describe('terminal link provider with wrapped table URLs', () => {
expect(segments[2].range.end.x).toBe(TABLE[3].text.length - 1);
});
it('links the column on a soft-wrapped URL row and the row below it separately', () => {
const { provide } = harness(SOFT_WRAPPED_URL_ROWS, SOFT_WRAP_COLS);
const texts = [1, 2, 3].flatMap((line) => provide(line).map((link) => link.text));
expect(texts.filter((text) => text.includes('report.txtccc'))).toEqual([]);
expect(provide(2).map((link) => link.text)).toContain('/tmp/report.txt');
expect(provide(3).map((link) => link.text)).toContain('ccc/x.html');
});
it('keeps a single-row URL with a paren pair whole', () => {
const line = 'Open https://example.com/wiki/Widget_(tool) please';
const { provide } = harness([{ text: line }], 80);