diff --git a/src/features/messages/components/Markdown.test.tsx b/src/features/messages/components/Markdown.test.tsx
index 5a76f69a7..dd75ce237 100644
--- a/src/features/messages/components/Markdown.test.tsx
+++ b/src/features/messages/components/Markdown.test.tsx
@@ -273,4 +273,43 @@ describe("Markdown file-like href behavior", () => {
expect(clickEvent.defaultPrevented).toBe(true);
expect(onOpenFileLink).not.toHaveBeenCalled();
});
+
+ it("does not turn natural-language slash phrases into file links", () => {
+ const { container } = render(
+ ,
+ );
+
+ expect(container.querySelector(".message-file-link")).toBeNull();
+ expect(container.textContent).toContain("app/daemon");
+ expect(container.textContent).toContain("Git/Plan");
+ });
+
+ it("does not turn longer slash phrases into file links", () => {
+ const { container } = render(
+ ,
+ );
+
+ expect(container.querySelector(".message-file-link")).toBeNull();
+ expect(container.textContent).toContain("Spec/Verification/Evidence");
+ });
+
+ it("still turns clear file paths in plain text into file links", () => {
+ const { container } = render(
+ ,
+ );
+
+ const fileLinks = [...container.querySelectorAll(".message-file-link")];
+ expect(fileLinks).toHaveLength(2);
+ expect(fileLinks[0]?.textContent).toContain("setup.md");
+ expect(fileLinks[1]?.textContent).toContain("index.ts");
+ });
});
diff --git a/src/utils/remarkFileLinks.ts b/src/utils/remarkFileLinks.ts
index ca9682df9..4824452fa 100644
--- a/src/utils/remarkFileLinks.ts
+++ b/src/utils/remarkFileLinks.ts
@@ -9,17 +9,7 @@ const FILE_PATH_PATTERN =
const FILE_PATH_MATCH = new RegExp(`^${FILE_PATH_PATTERN.source}$`);
const TRAILING_PUNCTUATION = new Set([".", ",", ";", ":", "!", "?", ")", "]", "}"]);
-const RELATIVE_ALLOWED_PREFIXES = [
- "src/",
- "app/",
- "lib/",
- "tests/",
- "test/",
- "packages/",
- "apps/",
- "docs/",
- "scripts/",
-];
+const LETTER_OR_NUMBER_PATTERN = /[\p{L}\p{N}.]/u;
type MarkdownNode = {
type: string;
@@ -43,7 +33,11 @@ function isPathCandidate(
return false;
}
if (value.startsWith("/") || value.startsWith("./") || value.startsWith("../")) {
- if (value.startsWith("/") && previousChar && /[A-Za-z0-9.]/.test(previousChar)) {
+ if (
+ value.startsWith("/") &&
+ previousChar &&
+ LETTER_OR_NUMBER_PATTERN.test(previousChar)
+ ) {
return false;
}
return true;
@@ -52,10 +46,7 @@ function isPathCandidate(
return true;
}
const lastSegment = value.split("/").pop() ?? "";
- if (lastSegment.includes(".")) {
- return true;
- }
- return RELATIVE_ALLOWED_PREFIXES.some((prefix) => value.startsWith(prefix));
+ return lastSegment.includes(".");
}
function splitTrailingPunctuation(value: string) {