mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 10:39:32 +01:00
fix: apply the review items for #687 at merge
- constants.js:2296,2301 spacedFilePathOnLine: refuse a first word ending in `$` and an earlier word with no letter or digit (other than a bare `-`), so a shell prompt showing an absolute working directory (`/mnt/c/proj ❯ code notes.md`, `/home/me/proj$ cat notes.md`) keeps master's links; the six rows from the review are pinned, plus OneDrive, `Program Files (x86)` and `Docs - Copy` still linking whole. - constants.js:2312: the leading strip is now `/^(?:~?\/|(?:\.\.?\/)+)/`, so `Saved to: ../My Docs/plan.md` links whole; an interior `..` still links nothing. Tests for the detector and the terminal provider. - app.js:3032 _linkifyFilePaths: carry any leading bold label and let spacedFilePathOnLine() judge it, and give a text node that follows another inline element a placeholder word, so `**Note:** /home/me/proj/out report.pdf` and ``Use `--config` /home/me/proj/cfg data.json`` split as in the terminal; a spaced path inside inline code still links whole. The now-unused label-pattern guard is gone. - JSDoc (findFilePathLinks, SPACED_FILE_PATH_LABEL_PATTERN, spacedFilePathOnLine) and the spaced-path paragraph in docs/architecture-invariants.md updated to match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
df9f93d3ee
commit
e52cc60c7c
5 files changed
+91
-18
No files matched your search
@@ -121,6 +121,28 @@ describe('response viewer file-path linkifier', () => {
|
||||
expect(paths(linkify(renderChat(markdown))).map((a) => a.getAttribute('data-path'))).toEqual(expected);
|
||||
});
|
||||
|
||||
// The terminal splits these lines (`Note:` is not a path label, and the path does
|
||||
// not start the line), so the viewer must split them too.
|
||||
it.each([
|
||||
['**Note:** /home/me/proj/out report.pdf', ['/home/me/proj/out', 'report.pdf']],
|
||||
['Use `--config` /home/me/proj/cfg data.json', ['/home/me/proj/cfg', 'data.json']],
|
||||
])('splits a spaced candidate the terminal splits: %s', (markdown, expected) => {
|
||||
const html = renderChat(markdown);
|
||||
const original = document.createElement('div');
|
||||
original.innerHTML = html;
|
||||
const root = linkify(html);
|
||||
expect(paths(root).map((a) => a.getAttribute('data-path'))).toEqual(expected);
|
||||
expect(root.textContent).toBe(original.textContent);
|
||||
});
|
||||
|
||||
it('still links a spaced path inside inline code whole, after another inline element too', () => {
|
||||
const root = linkify(renderChat('Use `--config` `/home/me/My Docs/cfg data.json`'));
|
||||
|
||||
const links = paths(root);
|
||||
expect(links.map((a) => a.getAttribute('data-path'))).toEqual(['/home/me/My Docs/cfg data.json']);
|
||||
expect(links[0].closest('code')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('does not inherit a bold label from earlier prose or another block', () => {
|
||||
for (const markdown of [
|
||||
'See **Saved to:** 03 Attachments/Build SIPOC Design/Build-SIPOC.pptx',
|
||||
|
||||
@@ -326,6 +326,37 @@ describe('spaced file paths: shapes that keep master links', () => {
|
||||
expect(paths('Saved to: ./My Docs/plan.md')).toEqual(['./My Docs/plan.md']);
|
||||
expect(paths('Saved to: ./notes.md')).toEqual(['./notes.md']);
|
||||
});
|
||||
|
||||
it('reads a leading run of ../ as parent directories, not segments', () => {
|
||||
expect(paths('Saved to: ../My Docs/plan.md')).toEqual(['../My Docs/plan.md']);
|
||||
expect(paths('Saved to: ../../My Docs/plan.md')).toEqual(['../../My Docs/plan.md']);
|
||||
expect(paths('Saved to: ../notes.md')).toEqual(['../notes.md']);
|
||||
// An interior `..` is still a segment, so the span links nothing.
|
||||
expect(paths('Saved to: My Docs/../plan.md')).toEqual([]);
|
||||
expect(paths('Saved to: ../My Docs/../x/plan.md')).toEqual([]);
|
||||
});
|
||||
|
||||
// A shell prompt that prints its working directory in full (WSL's `/mnt/c/...` is
|
||||
// outside `$HOME`): a word with no letter or digit, or a first word ending in `$`,
|
||||
// is never part of a file name, so every earlier command in the scrollback keeps
|
||||
// master's links.
|
||||
it.each([
|
||||
['/mnt/c/proj ❯ code notes.md', ['/mnt/c/proj', true], ['notes.md']],
|
||||
['/home/me/proj $ cat notes.md', ['/home/me/proj', true], ['notes.md']],
|
||||
['/home/me/proj$ cat notes.md', ['/home/me/proj', true], ['notes.md']],
|
||||
['/home/me/proj ❯ git add src/a.ts', ['/home/me/proj', true], ['src/a.ts']],
|
||||
['/mnt/c/Users/me/OneDrive - Contoso/proj ❯ code notes.md', ['/mnt/c/Users/me/OneDrive', true], ['notes.md']],
|
||||
['/home/me/proj/out ✓ report.pdf', ['/home/me/proj/out', true], ['report.pdf']],
|
||||
] as Array<[string, ...Array<[string, true?]>]>)('keeps a shell prompt out of the path: %s', (line, ...links) => {
|
||||
expect(findFilePathLinks(line)).toEqual(masterLinks(line, ...links));
|
||||
});
|
||||
|
||||
it.each([LONG, '/mnt/c/Program Files (x86)/app/readme.txt', '/mnt/c/Users/me/Docs - Copy/a.docx'])(
|
||||
'keeps a name whose words hold a letter or digit, or a bare -, whole: %s',
|
||||
(line) => {
|
||||
expect(paths(line)).toEqual([line]);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('terminal link provider with spaced paths', () => {
|
||||
@@ -383,6 +414,13 @@ describe('terminal link provider with spaced paths', () => {
|
||||
expect(opened).toEqual([`/workspace/project/${rel}`]);
|
||||
});
|
||||
|
||||
it('links a labelled spaced path under ../ and opens it outside the workspace', () => {
|
||||
const { links, opened } = linksFor('Saved to: ../My Docs/plan.md');
|
||||
expect(links.map((l) => l.text)).toEqual(['../My Docs/plan.md']);
|
||||
links[0].activate(null, links[0].text);
|
||||
expect(opened).toEqual(['/workspace/My Docs/plan.md']);
|
||||
});
|
||||
|
||||
it('links nothing for an unlinkable spaced path', () => {
|
||||
expect(linksFor('/etc/secret files/passwords.txt').links).toEqual([]);
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user