import { describe, expect, it } from "vite-plus/test";import { createElement } from "react";import { renderToStaticMarkup } from "react-dom/server";import ReactMarkdown from "react-markdown"; import { extractMarkdownLinkHrefs, isWindowsDrivePathHref, resolveInlineCodeFileLinkMeta, resolveMarkdownFileLinkMeta, resolveMarkdownFileLinkTarget, rewriteMarkdownFileUriHref, shouldOpenMarkdownFileLinkInBrowserByDefault, shouldOpenMarkdownFileLinkInEditor,} from "./markdown-links"; describe("isWindowsDrivePathHref", () => { it.each([ ["C:\\repo\\image.png", true], ["C:%5Crepo%5Cimage.png", true], ["https://example.com/image.png", false], ])("classifies %s as %s", (href, expected) => { expect(isWindowsDrivePathHref(href)).toBe(expected); });}); function renderMarkdownLinkHref(markdown: string): string | undefined { let renderedHref: string | undefined; renderToStaticMarkup( createElement( ReactMarkdown, { components: { a({ href }) { renderedHref = href; return createElement("a", { href }); }, }, }, markdown, ), ); return renderedHref;} describe("extractMarkdownLinkHrefs", () => { it("extracts angle-bracketed paths containing spaces", () => { expect( extractMarkdownLinkHrefs( "[Open the Bike Receipts folder](</Users/dara/Downloads/Lime Ride Artifacts/Bike Receipts>)", ), ).toEqual(["/Users/dara/Downloads/Lime Ride Artifacts/Bike Receipts"]); }); it("preserves ordinary destinations and ignores link titles", () => { expect( extractMarkdownLinkHrefs( '[source](apps/web/src/markdown-links.ts "implementation") and [docs](https://example.com)', ), ).toEqual(["apps/web/src/markdown-links.ts", "https://example.com"]); });}); describe("shouldOpenMarkdownFileLinkInEditor", () => { it("uses command-click on macOS", () => { expect(shouldOpenMarkdownFileLinkInEditor({ metaKey: true, ctrlKey: false }, "MacIntel")).toBe( true, ); expect(shouldOpenMarkdownFileLinkInEditor({ metaKey: false, ctrlKey: true }, "MacIntel")).toBe( false, ); }); it("uses control-click on other platforms", () => { expect( shouldOpenMarkdownFileLinkInEditor({ metaKey: false, ctrlKey: true }, "Linux x86_64"), ).toBe(true); expect( shouldOpenMarkdownFileLinkInEditor({ metaKey: true, ctrlKey: false }, "Linux x86_64"), ).toBe(false); });}); describe("shouldOpenMarkdownFileLinkInBrowserByDefault", () => { it("keeps PDFs browser-first while source files open in the file viewer", () => { expect(shouldOpenMarkdownFileLinkInBrowserByDefault("report.pdf")).toBe(true); expect(shouldOpenMarkdownFileLinkInBrowserByDefault("report.PDF?download=1")).toBe(true); expect(shouldOpenMarkdownFileLinkInBrowserByDefault("report.html")).toBe(false); expect(shouldOpenMarkdownFileLinkInBrowserByDefault("report.xml")).toBe(false); });}); describe("rewriteMarkdownFileUriHref", () => { it("rewrites file uri hrefs into direct path hrefs", () => { expect(rewriteMarkdownFileUriHref("file:///Users/julius/project/src/main.ts#L42")).toBe( "/Users/julius/project/src/main.ts#L42", ); }); it("preserves encoded octets so file paths are decoded only once later", () => { expect(rewriteMarkdownFileUriHref("file:///Users/julius/project/file%2520name.md")).toBe( "/Users/julius/project/file%2520name.md", ); }); it("normalizes file uri hrefs for windows drive paths", () => { expect( rewriteMarkdownFileUriHref( "file:///D:/Programme/t3code/apps/web/src/components/chat/OpenInPicker.tsx#L69", ), ).toBe("D:/Programme/t3code/apps/web/src/components/chat/OpenInPicker.tsx#L69"); }); it("preserves file uri authorities as windows UNC paths", () => { expect(rewriteMarkdownFileUriHref("file://server/share/workspace-image.svg")).toBe( "\\\\server\\share\\workspace-image.svg", ); }); it("treats a localhost file uri as a local path", () => { expect(rewriteMarkdownFileUriHref("file://localhost/home/me/notes.md")).toBe( "/home/me/notes.md", ); }); it("unwraps angle-bracketed file uri hrefs", () => { expect( rewriteMarkdownFileUriHref(" <file:///D:/Programme/t3code/apps/web/src/markdown-links.ts> "), ).toBe("D:/Programme/t3code/apps/web/src/markdown-links.ts"); });}); describe("resolveMarkdownFileLinkTarget", () => { it("resolves absolute posix file paths", () => { expect(resolveMarkdownFileLinkTarget("/Users/julius/project/AGENTS.md")).toBe( "/Users/julius/project/AGENTS.md", ); }); it("resolves relative file paths against cwd", () => { expect(resolveMarkdownFileLinkTarget("src/processRunner.ts:71", "/Users/julius/project")).toBe( "/Users/julius/project/src/processRunner.ts:71", ); }); it("does not treat filename line references as external schemes", () => { expect(resolveMarkdownFileLinkTarget("script.ts:10", "/Users/julius/project")).toBe( "/Users/julius/project/script.ts:10", ); }); it("resolves bare file names against cwd", () => { expect(resolveMarkdownFileLinkTarget("AGENTS.md", "/Users/julius/project")).toBe( "/Users/julius/project/AGENTS.md", ); }); it("maps #L line anchors to editor line suffixes", () => { expect(resolveMarkdownFileLinkTarget("/Users/julius/project/src/main.ts#L42C7")).toBe( "/Users/julius/project/src/main.ts:42:7", ); }); it("ignores external urls", () => { expect(resolveMarkdownFileLinkTarget("https://example.com/docs")).toBeNull(); expect(resolveMarkdownFileLinkTarget("//cdn.example.com/clip.mp4", "/workspace")).toBeNull(); }); it("does not double-decode file URLs", () => { expect(resolveMarkdownFileLinkTarget("file:///Users/julius/project/file%2520name.md")).toBe( "/Users/julius/project/file%20name.md", ); }); it("resolves file uri authorities as windows UNC paths", () => { expect(resolveMarkdownFileLinkTarget("file://server/share/workspace-image.svg")).toBe( "\\\\server\\share\\workspace-image.svg", ); }); it("resolves a localhost file uri as a local path", () => { expect(resolveMarkdownFileLinkTarget("file://localhost/home/me/notes.md")).toBe( "/home/me/notes.md", ); }); it("formats tooltip display paths relative to the cwd when possible", () => { expect( resolveMarkdownFileLinkMeta( "file:///C:/Users/mike/dev-stuff/t3code/apps/web/src/session-logic.ts#L501", "C:/Users/mike/dev-stuff/t3code", ), ).toMatchObject({ displayPath: "t3code/apps/web/src/session-logic.ts:501", workspaceRelativePath: "apps/web/src/session-logic.ts", }); }); it("resolves the encoded spaces emitted by the markdown renderer", () => { expect( resolveMarkdownFileLinkMeta( "/Users/dara/Downloads/Lime%20Ride%20Artifacts/Bike%20Receipts", "/Users/dara/Downloads/Lime Ride Artifacts", ), ).toMatchObject({ targetPath: "/Users/dara/Downloads/Lime Ride Artifacts/Bike Receipts", workspaceRelativePath: "Bike Receipts", basename: "Bike Receipts", }); }); it("resolves relative spaced folders from the markdown renderer", () => { const href = renderMarkdownLinkHref("[folder](<docs/My Folder>)"); expect(href).toBe("docs/My%20Folder"); expect(resolveMarkdownFileLinkMeta(href, "/repo/project")).toMatchObject({ targetPath: "/repo/project/docs/My Folder", workspaceRelativePath: "docs/My Folder", basename: "My Folder", }); }); it.each(["md", "html", "xml"])( "resolves a bare spaced .%s filename from the markdown renderer", (extension) => { const href = renderMarkdownLinkHref(`[checklist](<Updated cutover checklist.${extension}>)`); expect(href).toBe(`Updated%20cutover%20checklist.${extension}`); expect(resolveMarkdownFileLinkMeta(href, "/repo/project")).toMatchObject({ targetPath: `/repo/project/Updated cutover checklist.${extension}`, workspaceRelativePath: `Updated cutover checklist.${extension}`, basename: `Updated cutover checklist.${extension}`, }); }, ); it("formats tooltip display paths relative to the cwd for slash-prefixed windows paths", () => { expect( resolveMarkdownFileLinkMeta( "/C:/Users/mike/dev-stuff/t3code/apps/web/src/components/chat/MessagesTimeline.virtualization.browser.tsx", "C:/Users/mike/dev-stuff/t3code", ), ).toMatchObject({ displayPath: "t3code/apps/web/src/components/chat/MessagesTimeline.virtualization.browser.tsx", workspaceRelativePath: "apps/web/src/components/chat/MessagesTimeline.virtualization.browser.tsx", }); }); it("does not create a preview path for files outside the workspace", () => { expect(resolveMarkdownFileLinkMeta("/tmp/report.ts", "/repo/project")).toMatchObject({ workspaceRelativePath: null, }); }); it("normalizes slash-prefixed windows drive paths before resolving", () => { expect( resolveMarkdownFileLinkTarget( "/D:/Programme/t3code/apps/web/src/components/chat/OpenInPicker.tsx#L69", ), ).toBe("D:/Programme/t3code/apps/web/src/components/chat/OpenInPicker.tsx:69"); }); it("resolves angle-bracketed windows drive paths", () => { expect( resolveMarkdownFileLinkTarget( "</D:/Programme/t3code/apps/web/src/components/ChatMarkdown.tsx:1>", ), ).toBe("D:/Programme/t3code/apps/web/src/components/ChatMarkdown.tsx:1"); }); it("does not treat app routes as file links, even with a line anchor", () => { expect(resolveMarkdownFileLinkTarget("/chat/settings")).toBeNull(); expect(resolveMarkdownFileLinkTarget("/chat/settings#L3", "/repo")).toBeNull(); }); it("decodes an encoded drive colon in a file uri before dropping its slash", () => { expect(resolveMarkdownFileLinkTarget("file:///c%3A/Users/x/shot.png")).toBe( "c:/Users/x/shot.png", ); });}); describe("relative links inside a rendered host file", () => { it("anchor to the file's directory while workspace membership follows cwd", () => { const meta = resolveMarkdownFileLinkMeta("appendix.md", "/repo", "/tmp/report"); expect(meta).toMatchObject({ filePath: "/tmp/report/appendix.md", workspaceRelativePath: null, }); const inline = resolveInlineCodeFileLinkMeta("Makefile:12", "/repo", "/tmp/report"); expect(inline).toMatchObject({ filePath: "/tmp/report/Makefile", line: 12 }); expect(resolveMarkdownFileLinkMeta("src/main.ts", "/repo", "/repo/docs")).toMatchObject({ filePath: "/repo/docs/src/main.ts", workspaceRelativePath: "docs/src/main.ts", }); });}); describe("resolveInlineCodeFileLinkMeta", () => { it("links relative paths with file extensions", () => { expect( resolveInlineCodeFileLinkMeta("docs/internals/workspace-layout.md", "/Users/julius/project"), ).toMatchObject({ targetPath: "/Users/julius/project/docs/internals/workspace-layout.md", basename: "workspace-layout.md", }); }); it("links absolute posix paths", () => { expect(resolveInlineCodeFileLinkMeta("/Users/julius/project/AGENTS.md")).toMatchObject({ targetPath: "/Users/julius/project/AGENTS.md", }); expect(resolveInlineCodeFileLinkMeta("/usr/local/bin/tool")).toMatchObject({ targetPath: "/usr/local/bin/tool", }); expect(resolveInlineCodeFileLinkMeta("/workspace/Makefile")).toMatchObject({ basename: "Makefile", }); expect(resolveInlineCodeFileLinkMeta("/chat/settings")).toBeNull(); }); it("links windows drive paths", () => { expect(resolveInlineCodeFileLinkMeta("C:\\Users\\mike\\project\\src\\main.ts")).toMatchObject({ basename: "main.ts", }); }); it("links relative paths with line positions", () => { expect( resolveInlineCodeFileLinkMeta("src/processRunner.ts:71", "/Users/julius/project"), ).toMatchObject({ targetPath: "/Users/julius/project/src/processRunner.ts:71", line: 71, }); }); it("links bare filenames only when a line suffix marks them as file references", () => { expect(resolveInlineCodeFileLinkMeta("script.ts:10", "/Users/julius/project")).toMatchObject({ targetPath: "/Users/julius/project/script.ts:10", line: 10, }); expect(resolveInlineCodeFileLinkMeta("AGENTS.md", "/Users/julius/project")).toBeNull(); }); it("links extensionless bare filenames with a line suffix", () => { expect(resolveInlineCodeFileLinkMeta("Makefile:12", "/Users/julius/project")).toMatchObject({ targetPath: "/Users/julius/project/Makefile:12", basename: "Makefile", line: 12, }); expect(resolveInlineCodeFileLinkMeta("Dockerfile:8:2", "/Users/julius/project")).toMatchObject({ line: 8, column: 2, }); expect(resolveInlineCodeFileLinkMeta("Makefile:12")).toBeNull(); }); it("does not treat arbitrary name:digits shapes as files", () => { expect(resolveInlineCodeFileLinkMeta("error:1", "/Users/julius/project")).toBeNull(); expect(resolveInlineCodeFileLinkMeta("TODO:12", "/Users/julius/project")).toBeNull(); expect(resolveInlineCodeFileLinkMeta("exit:0", "/Users/julius/project")).toBeNull(); expect(resolveInlineCodeFileLinkMeta("port:3000", "/Users/julius/project")).toBeNull(); expect(resolveInlineCodeFileLinkMeta("http:80", "/Users/julius/project")).toBeNull(); }); it("links dot-prefixed relative paths without extensions", () => { expect( resolveInlineCodeFileLinkMeta("./scripts/deploy", "/Users/julius/project"), ).toMatchObject({ basename: "deploy", }); }); it("links relative windows-style paths by normalizing backslashes", () => { expect(resolveInlineCodeFileLinkMeta("src\\main.ts", "/Users/julius/project")).toMatchObject({ targetPath: "/Users/julius/project/src/main.ts", basename: "main.ts", }); expect( resolveInlineCodeFileLinkMeta(".\\scripts\\deploy", "/Users/julius/project"), ).toMatchObject({ basename: "deploy", }); }); it("ignores hosts, ports, and versions", () => { expect(resolveInlineCodeFileLinkMeta("127.0.0.1:3000", "/Users/julius/project")).toBeNull(); expect(resolveInlineCodeFileLinkMeta("localhost:3000", "/Users/julius/project")).toBeNull(); expect( resolveInlineCodeFileLinkMeta("example.com/index.html", "/Users/julius/project"), ).toBeNull(); expect(resolveInlineCodeFileLinkMeta("example.com:8080", "/Users/julius/project")).toBeNull(); expect(resolveInlineCodeFileLinkMeta("10.0.0.1:80:1", "/Users/julius/project")).toBeNull(); expect( resolveInlineCodeFileLinkMeta("localhost/index.html", "/Users/julius/project"), ).toBeNull(); expect( resolveInlineCodeFileLinkMeta("example.uk/index.html", "/Users/julius/project"), ).toBeNull(); }); it("still links files whose extension merely resembles a tld", () => { expect(resolveInlineCodeFileLinkMeta("script.ts:10", "/Users/julius/project")).not.toBeNull(); expect(resolveInlineCodeFileLinkMeta("src/setup.sh:3", "/Users/julius/project")).not.toBeNull(); expect(resolveInlineCodeFileLinkMeta("Makefile.in:12", "/Users/julius/project")).not.toBeNull(); expect( resolveInlineCodeFileLinkMeta("conf.d/nginx.conf", "/Users/julius/project"), ).not.toBeNull(); }); it("prefers file over country-code host when a line suffix is present", () => { expect(resolveInlineCodeFileLinkMeta("script.pl:10", "/Users/julius/project")).toMatchObject({ targetPath: "/Users/julius/project/script.pl:10", line: 10, }); expect(resolveInlineCodeFileLinkMeta("model.pt:3", "/Users/julius/project")).not.toBeNull(); expect( resolveInlineCodeFileLinkMeta("example.pl/index.html", "/Users/julius/project"), ).toBeNull(); expect(resolveInlineCodeFileLinkMeta("example.com:8080", "/Users/julius/project")).toBeNull(); }); it("ignores commands, flags, and expressions", () => { expect(resolveInlineCodeFileLinkMeta("git worktree list --porcelain")).toBeNull(); expect(resolveInlineCodeFileLinkMeta("node.meta", "/Users/julius/project")).toBeNull(); expect(resolveInlineCodeFileLinkMeta("pnpm install", "/Users/julius/project")).toBeNull(); expect(resolveInlineCodeFileLinkMeta("src/**/*.ts", "/Users/julius/project")).toBeNull(); }); it("ignores extension-less relative segments like git refs and directories", () => { expect(resolveInlineCodeFileLinkMeta("origin/main", "/Users/julius/project")).toBeNull(); expect(resolveInlineCodeFileLinkMeta("apps/web", "/Users/julius/project")).toBeNull(); }); it("ignores external urls", () => { expect(resolveInlineCodeFileLinkMeta("https://example.com/docs.html")).toBeNull(); }); it("ignores relative paths without a cwd to resolve against", () => { expect(resolveInlineCodeFileLinkMeta("docs/internals/workspace-layout.md")).toBeNull(); });}); describe("directory paths with a trailing separator", () => { it("keeps the final segment for a POSIX directory path", () => { expect(resolveMarkdownFileLinkMeta("/tmp/favicons/", "/repo/project")).toMatchObject({ basename: "favicons", }); }); it("keeps the final segment for a Windows directory path", () => { expect( resolveMarkdownFileLinkMeta("C:\\Users\\kelchm\\.claude\\", "/repo/project"), ).toMatchObject({ basename: ".claude" }); }); it("matches the label of the same path without a trailing separator", () => { const withSlash = resolveMarkdownFileLinkMeta("/tmp/favicons/", "/repo/project"); const withoutSlash = resolveMarkdownFileLinkMeta("/tmp/favicons", "/repo/project"); expect(withSlash?.basename).toBe(withoutSlash?.basename); }); it("does not produce an empty label for the filesystem root", () => { const meta = resolveMarkdownFileLinkMeta("/tmp/", "/repo/project"); expect(meta?.basename).not.toBe(""); });});
import { describe, expect, it } from "vite-plus/test";
import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import ReactMarkdown from "react-markdown";
import {
extractMarkdownLinkHrefs,
isWindowsDrivePathHref,
resolveInlineCodeFileLinkMeta,
resolveMarkdownFileLinkMeta,
resolveMarkdownFileLinkTarget,
rewriteMarkdownFileUriHref,
shouldOpenMarkdownFileLinkInBrowserByDefault,
shouldOpenMarkdownFileLinkInEditor,
} from "./markdown-links";
describe("isWindowsDrivePathHref", () => {
it.each([
["C:\\repo\\image.png", true],
["C:%5Crepo%5Cimage.png", true],
["https://example.com/image.png", false],
])("classifies %s as %s", (href, expected) => {
expect(isWindowsDrivePathHref(href)).toBe(expected);
});
});
function renderMarkdownLinkHref(markdown: string): string | undefined {
let renderedHref: string | undefined;
renderToStaticMarkup(
createElement(
ReactMarkdown,
{
components: {
a({ href }) {
renderedHref = href;
return createElement("a", { href });
},
},
},
markdown,
),
);
return renderedHref;
}
describe("extractMarkdownLinkHrefs", () => {
it("extracts angle-bracketed paths containing spaces", () => {
expect(
extractMarkdownLinkHrefs(
"[Open the Bike Receipts folder](</Users/dara/Downloads/Lime Ride Artifacts/Bike Receipts>)",
),
).toEqual(["/Users/dara/Downloads/Lime Ride Artifacts/Bike Receipts"]);
});
it("preserves ordinary destinations and ignores link titles", () => {
expect(
extractMarkdownLinkHrefs(
'[source](apps/web/src/markdown-links.ts "implementation") and [docs](https://example.com)',
),
).toEqual(["apps/web/src/markdown-links.ts", "https://example.com"]);
});
});
describe("shouldOpenMarkdownFileLinkInEditor", () => {
it("uses command-click on macOS", () => {
expect(shouldOpenMarkdownFileLinkInEditor({ metaKey: true, ctrlKey: false }, "MacIntel")).toBe(
true,
);
expect(shouldOpenMarkdownFileLinkInEditor({ metaKey: false, ctrlKey: true }, "MacIntel")).toBe(
false,
);
});
it("uses control-click on other platforms", () => {
expect(
shouldOpenMarkdownFileLinkInEditor({ metaKey: false, ctrlKey: true }, "Linux x86_64"),
).toBe(true);
expect(
shouldOpenMarkdownFileLinkInEditor({ metaKey: true, ctrlKey: false }, "Linux x86_64"),
).toBe(false);
});
});
describe("shouldOpenMarkdownFileLinkInBrowserByDefault", () => {
it("keeps PDFs browser-first while source files open in the file viewer", () => {
expect(shouldOpenMarkdownFileLinkInBrowserByDefault("report.pdf")).toBe(true);
expect(shouldOpenMarkdownFileLinkInBrowserByDefault("report.PDF?download=1")).toBe(true);
expect(shouldOpenMarkdownFileLinkInBrowserByDefault("report.html")).toBe(false);
expect(shouldOpenMarkdownFileLinkInBrowserByDefault("report.xml")).toBe(false);
});
});
describe("rewriteMarkdownFileUriHref", () => {
it("rewrites file uri hrefs into direct path hrefs", () => {
expect(rewriteMarkdownFileUriHref("file:///Users/julius/project/src/main.ts#L42")).toBe(
"/Users/julius/project/src/main.ts#L42",
);
});
it("preserves encoded octets so file paths are decoded only once later", () => {
expect(rewriteMarkdownFileUriHref("file:///Users/julius/project/file%2520name.md")).toBe(
"/Users/julius/project/file%2520name.md",
);
});
it("normalizes file uri hrefs for windows drive paths", () => {
expect(
rewriteMarkdownFileUriHref(
"file:///D:/Programme/t3code/apps/web/src/components/chat/OpenInPicker.tsx#L69",
),
).toBe("D:/Programme/t3code/apps/web/src/components/chat/OpenInPicker.tsx#L69");
});
it("preserves file uri authorities as windows UNC paths", () => {
expect(rewriteMarkdownFileUriHref("file://server/share/workspace-image.svg")).toBe(
"\\\\server\\share\\workspace-image.svg",
);
});
it("treats a localhost file uri as a local path", () => {
expect(rewriteMarkdownFileUriHref("file://localhost/home/me/notes.md")).toBe(
"/home/me/notes.md",
);
});
it("unwraps angle-bracketed file uri hrefs", () => {
expect(
rewriteMarkdownFileUriHref(" <file:///D:/Programme/t3code/apps/web/src/markdown-links.ts> "),
).toBe("D:/Programme/t3code/apps/web/src/markdown-links.ts");
});
});
describe("resolveMarkdownFileLinkTarget", () => {
it("resolves absolute posix file paths", () => {
expect(resolveMarkdownFileLinkTarget("/Users/julius/project/AGENTS.md")).toBe(
"/Users/julius/project/AGENTS.md",
);
});
it("resolves relative file paths against cwd", () => {
expect(resolveMarkdownFileLinkTarget("src/processRunner.ts:71", "/Users/julius/project")).toBe(
"/Users/julius/project/src/processRunner.ts:71",
);
});
it("does not treat filename line references as external schemes", () => {
expect(resolveMarkdownFileLinkTarget("script.ts:10", "/Users/julius/project")).toBe(
"/Users/julius/project/script.ts:10",
);
});
it("resolves bare file names against cwd", () => {
expect(resolveMarkdownFileLinkTarget("AGENTS.md", "/Users/julius/project")).toBe(
"/Users/julius/project/AGENTS.md",
);
});
it("maps #L line anchors to editor line suffixes", () => {
expect(resolveMarkdownFileLinkTarget("/Users/julius/project/src/main.ts#L42C7")).toBe(
"/Users/julius/project/src/main.ts:42:7",
);
});
it("ignores external urls", () => {
expect(resolveMarkdownFileLinkTarget("https://example.com/docs")).toBeNull();
expect(resolveMarkdownFileLinkTarget("//cdn.example.com/clip.mp4", "/workspace")).toBeNull();
});
it("does not double-decode file URLs", () => {
expect(resolveMarkdownFileLinkTarget("file:///Users/julius/project/file%2520name.md")).toBe(
"/Users/julius/project/file%20name.md",
);
});
it("resolves file uri authorities as windows UNC paths", () => {
expect(resolveMarkdownFileLinkTarget("file://server/share/workspace-image.svg")).toBe(
"\\\\server\\share\\workspace-image.svg",
);
});
it("resolves a localhost file uri as a local path", () => {
expect(resolveMarkdownFileLinkTarget("file://localhost/home/me/notes.md")).toBe(
"/home/me/notes.md",
);
});
it("formats tooltip display paths relative to the cwd when possible", () => {
expect(
resolveMarkdownFileLinkMeta(
"file:///C:/Users/mike/dev-stuff/t3code/apps/web/src/session-logic.ts#L501",
"C:/Users/mike/dev-stuff/t3code",
),
).toMatchObject({
displayPath: "t3code/apps/web/src/session-logic.ts:501",
workspaceRelativePath: "apps/web/src/session-logic.ts",
});
});
it("resolves the encoded spaces emitted by the markdown renderer", () => {
expect(
resolveMarkdownFileLinkMeta(
"/Users/dara/Downloads/Lime%20Ride%20Artifacts/Bike%20Receipts",
"/Users/dara/Downloads/Lime Ride Artifacts",
),
).toMatchObject({
targetPath: "/Users/dara/Downloads/Lime Ride Artifacts/Bike Receipts",
workspaceRelativePath: "Bike Receipts",
basename: "Bike Receipts",
});
});
it("resolves relative spaced folders from the markdown renderer", () => {
const href = renderMarkdownLinkHref("[folder](<docs/My Folder>)");
expect(href).toBe("docs/My%20Folder");
expect(resolveMarkdownFileLinkMeta(href, "/repo/project")).toMatchObject({
targetPath: "/repo/project/docs/My Folder",
workspaceRelativePath: "docs/My Folder",
basename: "My Folder",
});
});
it.each(["md", "html", "xml"])(
"resolves a bare spaced .%s filename from the markdown renderer",
(extension) => {
const href = renderMarkdownLinkHref(`[checklist](<Updated cutover checklist.${extension}>)`);
expect(href).toBe(`Updated%20cutover%20checklist.${extension}`);
expect(resolveMarkdownFileLinkMeta(href, "/repo/project")).toMatchObject({
targetPath: `/repo/project/Updated cutover checklist.${extension}`,
workspaceRelativePath: `Updated cutover checklist.${extension}`,
basename: `Updated cutover checklist.${extension}`,
});
},
);
it("formats tooltip display paths relative to the cwd for slash-prefixed windows paths", () => {
expect(
resolveMarkdownFileLinkMeta(
"/C:/Users/mike/dev-stuff/t3code/apps/web/src/components/chat/MessagesTimeline.virtualization.browser.tsx",
"C:/Users/mike/dev-stuff/t3code",
),
).toMatchObject({
displayPath:
"t3code/apps/web/src/components/chat/MessagesTimeline.virtualization.browser.tsx",
workspaceRelativePath:
"apps/web/src/components/chat/MessagesTimeline.virtualization.browser.tsx",
});
});
it("does not create a preview path for files outside the workspace", () => {
expect(resolveMarkdownFileLinkMeta("/tmp/report.ts", "/repo/project")).toMatchObject({
workspaceRelativePath: null,
});
});
it("normalizes slash-prefixed windows drive paths before resolving", () => {
expect(
resolveMarkdownFileLinkTarget(
"/D:/Programme/t3code/apps/web/src/components/chat/OpenInPicker.tsx#L69",
),
).toBe("D:/Programme/t3code/apps/web/src/components/chat/OpenInPicker.tsx:69");
});
it("resolves angle-bracketed windows drive paths", () => {
expect(
resolveMarkdownFileLinkTarget(
"</D:/Programme/t3code/apps/web/src/components/ChatMarkdown.tsx:1>",
),
).toBe("D:/Programme/t3code/apps/web/src/components/ChatMarkdown.tsx:1");
});
it("does not treat app routes as file links, even with a line anchor", () => {
expect(resolveMarkdownFileLinkTarget("/chat/settings")).toBeNull();
expect(resolveMarkdownFileLinkTarget("/chat/settings#L3", "/repo")).toBeNull();
});
it("decodes an encoded drive colon in a file uri before dropping its slash", () => {
expect(resolveMarkdownFileLinkTarget("file:///c%3A/Users/x/shot.png")).toBe(
"c:/Users/x/shot.png",
);
});
});
describe("relative links inside a rendered host file", () => {
it("anchor to the file's directory while workspace membership follows cwd", () => {
const meta = resolveMarkdownFileLinkMeta("appendix.md", "/repo", "/tmp/report");
expect(meta).toMatchObject({
filePath: "/tmp/report/appendix.md",
workspaceRelativePath: null,
});
const inline = resolveInlineCodeFileLinkMeta("Makefile:12", "/repo", "/tmp/report");
expect(inline).toMatchObject({ filePath: "/tmp/report/Makefile", line: 12 });
expect(resolveMarkdownFileLinkMeta("src/main.ts", "/repo", "/repo/docs")).toMatchObject({
filePath: "/repo/docs/src/main.ts",
workspaceRelativePath: "docs/src/main.ts",
});
});
});
describe("resolveInlineCodeFileLinkMeta", () => {
it("links relative paths with file extensions", () => {
expect(
resolveInlineCodeFileLinkMeta("docs/internals/workspace-layout.md", "/Users/julius/project"),
).toMatchObject({
targetPath: "/Users/julius/project/docs/internals/workspace-layout.md",
basename: "workspace-layout.md",
});
});
it("links absolute posix paths", () => {
expect(resolveInlineCodeFileLinkMeta("/Users/julius/project/AGENTS.md")).toMatchObject({
targetPath: "/Users/julius/project/AGENTS.md",
});
expect(resolveInlineCodeFileLinkMeta("/usr/local/bin/tool")).toMatchObject({
targetPath: "/usr/local/bin/tool",
});
expect(resolveInlineCodeFileLinkMeta("/workspace/Makefile")).toMatchObject({
basename: "Makefile",
});
expect(resolveInlineCodeFileLinkMeta("/chat/settings")).toBeNull();
});
it("links windows drive paths", () => {
expect(resolveInlineCodeFileLinkMeta("C:\\Users\\mike\\project\\src\\main.ts")).toMatchObject({
basename: "main.ts",
});
});
it("links relative paths with line positions", () => {
expect(
resolveInlineCodeFileLinkMeta("src/processRunner.ts:71", "/Users/julius/project"),
).toMatchObject({
targetPath: "/Users/julius/project/src/processRunner.ts:71",
line: 71,
});
});
it("links bare filenames only when a line suffix marks them as file references", () => {
expect(resolveInlineCodeFileLinkMeta("script.ts:10", "/Users/julius/project")).toMatchObject({
targetPath: "/Users/julius/project/script.ts:10",
line: 10,
});
expect(resolveInlineCodeFileLinkMeta("AGENTS.md", "/Users/julius/project")).toBeNull();
});
it("links extensionless bare filenames with a line suffix", () => {
expect(resolveInlineCodeFileLinkMeta("Makefile:12", "/Users/julius/project")).toMatchObject({
targetPath: "/Users/julius/project/Makefile:12",
basename: "Makefile",
line: 12,
});
expect(resolveInlineCodeFileLinkMeta("Dockerfile:8:2", "/Users/julius/project")).toMatchObject({
line: 8,
column: 2,
});
expect(resolveInlineCodeFileLinkMeta("Makefile:12")).toBeNull();
});
it("does not treat arbitrary name:digits shapes as files", () => {
expect(resolveInlineCodeFileLinkMeta("error:1", "/Users/julius/project")).toBeNull();
expect(resolveInlineCodeFileLinkMeta("TODO:12", "/Users/julius/project")).toBeNull();
expect(resolveInlineCodeFileLinkMeta("exit:0", "/Users/julius/project")).toBeNull();
expect(resolveInlineCodeFileLinkMeta("port:3000", "/Users/julius/project")).toBeNull();
expect(resolveInlineCodeFileLinkMeta("http:80", "/Users/julius/project")).toBeNull();
});
it("links dot-prefixed relative paths without extensions", () => {
expect(
resolveInlineCodeFileLinkMeta("./scripts/deploy", "/Users/julius/project"),
).toMatchObject({
basename: "deploy",
});
});
it("links relative windows-style paths by normalizing backslashes", () => {
expect(resolveInlineCodeFileLinkMeta("src\\main.ts", "/Users/julius/project")).toMatchObject({
targetPath: "/Users/julius/project/src/main.ts",
basename: "main.ts",
});
expect(
resolveInlineCodeFileLinkMeta(".\\scripts\\deploy", "/Users/julius/project"),
).toMatchObject({
basename: "deploy",
});
});
it("ignores hosts, ports, and versions", () => {
expect(resolveInlineCodeFileLinkMeta("127.0.0.1:3000", "/Users/julius/project")).toBeNull();
expect(resolveInlineCodeFileLinkMeta("localhost:3000", "/Users/julius/project")).toBeNull();
expect(
resolveInlineCodeFileLinkMeta("example.com/index.html", "/Users/julius/project"),
).toBeNull();
expect(resolveInlineCodeFileLinkMeta("example.com:8080", "/Users/julius/project")).toBeNull();
expect(resolveInlineCodeFileLinkMeta("10.0.0.1:80:1", "/Users/julius/project")).toBeNull();
expect(
resolveInlineCodeFileLinkMeta("localhost/index.html", "/Users/julius/project"),
).toBeNull();
expect(
resolveInlineCodeFileLinkMeta("example.uk/index.html", "/Users/julius/project"),
).toBeNull();
});
it("still links files whose extension merely resembles a tld", () => {
expect(resolveInlineCodeFileLinkMeta("script.ts:10", "/Users/julius/project")).not.toBeNull();
expect(resolveInlineCodeFileLinkMeta("src/setup.sh:3", "/Users/julius/project")).not.toBeNull();
expect(resolveInlineCodeFileLinkMeta("Makefile.in:12", "/Users/julius/project")).not.toBeNull();
expect(
resolveInlineCodeFileLinkMeta("conf.d/nginx.conf", "/Users/julius/project"),
).not.toBeNull();
});
it("prefers file over country-code host when a line suffix is present", () => {
expect(resolveInlineCodeFileLinkMeta("script.pl:10", "/Users/julius/project")).toMatchObject({
targetPath: "/Users/julius/project/script.pl:10",
line: 10,
});
expect(resolveInlineCodeFileLinkMeta("model.pt:3", "/Users/julius/project")).not.toBeNull();
expect(
resolveInlineCodeFileLinkMeta("example.pl/index.html", "/Users/julius/project"),
).toBeNull();
expect(resolveInlineCodeFileLinkMeta("example.com:8080", "/Users/julius/project")).toBeNull();
});
it("ignores commands, flags, and expressions", () => {
expect(resolveInlineCodeFileLinkMeta("git worktree list --porcelain")).toBeNull();
expect(resolveInlineCodeFileLinkMeta("node.meta", "/Users/julius/project")).toBeNull();
expect(resolveInlineCodeFileLinkMeta("pnpm install", "/Users/julius/project")).toBeNull();
expect(resolveInlineCodeFileLinkMeta("src/**/*.ts", "/Users/julius/project")).toBeNull();
});
it("ignores extension-less relative segments like git refs and directories", () => {
expect(resolveInlineCodeFileLinkMeta("origin/main", "/Users/julius/project")).toBeNull();
expect(resolveInlineCodeFileLinkMeta("apps/web", "/Users/julius/project")).toBeNull();
});
it("ignores external urls", () => {
expect(resolveInlineCodeFileLinkMeta("https://example.com/docs.html")).toBeNull();
});
it("ignores relative paths without a cwd to resolve against", () => {
expect(resolveInlineCodeFileLinkMeta("docs/internals/workspace-layout.md")).toBeNull();
});
});
describe("directory paths with a trailing separator", () => {
it("keeps the final segment for a POSIX directory path", () => {
expect(resolveMarkdownFileLinkMeta("/tmp/favicons/", "/repo/project")).toMatchObject({
basename: "favicons",
});
});
it("keeps the final segment for a Windows directory path", () => {
expect(
resolveMarkdownFileLinkMeta("C:\\Users\\kelchm\\.claude\\", "/repo/project"),
).toMatchObject({ basename: ".claude" });
});
it("matches the label of the same path without a trailing separator", () => {
const withSlash = resolveMarkdownFileLinkMeta("/tmp/favicons/", "/repo/project");
const withoutSlash = resolveMarkdownFileLinkMeta("/tmp/favicons", "/repo/project");
expect(withSlash?.basename).toBe(withoutSlash?.basename);
});
it("does not produce an empty label for the filesystem root", () => {
const meta = resolveMarkdownFileLinkMeta("/tmp/", "/repo/project");
expect(meta?.basename).not.toBe("");
});
});