Skip to content

Commit 3bf15bf

Browse files
authored
fix: prevent ambiguous slash phrases from rendering as file links (Dimillian#550)
1 parent 23b937d commit 3bf15bf

File tree

2 files changed

+46
-16
lines changed

2 files changed

+46
-16
lines changed

src/features/messages/components/Markdown.test.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,4 +273,43 @@ describe("Markdown file-like href behavior", () => {
273273
expect(clickEvent.defaultPrevented).toBe(true);
274274
expect(onOpenFileLink).not.toHaveBeenCalled();
275275
});
276+
277+
it("does not turn natural-language slash phrases into file links", () => {
278+
const { container } = render(
279+
<Markdown
280+
value="Keep the current app/daemon behavior and the existing Git/Plan experience."
281+
className="markdown"
282+
/>,
283+
);
284+
285+
expect(container.querySelector(".message-file-link")).toBeNull();
286+
expect(container.textContent).toContain("app/daemon");
287+
expect(container.textContent).toContain("Git/Plan");
288+
});
289+
290+
it("does not turn longer slash phrases into file links", () => {
291+
const { container } = render(
292+
<Markdown
293+
value="This keeps Spec/Verification/Evidence in the note without turning it into a file link."
294+
className="markdown"
295+
/>,
296+
);
297+
298+
expect(container.querySelector(".message-file-link")).toBeNull();
299+
expect(container.textContent).toContain("Spec/Verification/Evidence");
300+
});
301+
302+
it("still turns clear file paths in plain text into file links", () => {
303+
const { container } = render(
304+
<Markdown
305+
value="See docs/setup.md and /Users/example/project/src/index.ts for details."
306+
className="markdown"
307+
/>,
308+
);
309+
310+
const fileLinks = [...container.querySelectorAll(".message-file-link")];
311+
expect(fileLinks).toHaveLength(2);
312+
expect(fileLinks[0]?.textContent).toContain("setup.md");
313+
expect(fileLinks[1]?.textContent).toContain("index.ts");
314+
});
276315
});

src/utils/remarkFileLinks.ts

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,7 @@ const FILE_PATH_PATTERN =
99
const FILE_PATH_MATCH = new RegExp(`^${FILE_PATH_PATTERN.source}$`);
1010

1111
const TRAILING_PUNCTUATION = new Set([".", ",", ";", ":", "!", "?", ")", "]", "}"]);
12-
const RELATIVE_ALLOWED_PREFIXES = [
13-
"src/",
14-
"app/",
15-
"lib/",
16-
"tests/",
17-
"test/",
18-
"packages/",
19-
"apps/",
20-
"docs/",
21-
"scripts/",
22-
];
12+
const LETTER_OR_NUMBER_PATTERN = /[\p{L}\p{N}.]/u;
2313

2414
type MarkdownNode = {
2515
type: string;
@@ -43,7 +33,11 @@ function isPathCandidate(
4333
return false;
4434
}
4535
if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../")) {
46-
if (value.startsWith("/") && previousChar && /[A-Za-z0-9.]/.test(previousChar)) {
36+
if (
37+
value.startsWith("/") &&
38+
previousChar &&
39+
LETTER_OR_NUMBER_PATTERN.test(previousChar)
40+
) {
4741
return false;
4842
}
4943
return true;
@@ -52,10 +46,7 @@ function isPathCandidate(
5246
return true;
5347
}
5448
const lastSegment = value.split("/").pop() ?? "";
55-
if (lastSegment.includes(".")) {
56-
return true;
57-
}
58-
return RELATIVE_ALLOWED_PREFIXES.some((prefix) => value.startsWith(prefix));
49+
return lastSegment.includes(".");
5950
}
6051

6152
function splitTrailingPunctuation(value: string) {

0 commit comments

Comments
 (0)