History

fix(web): keep the final segment of directory paths with a trailing separator (#5460)

jorvarea committed 2 months ago

Commit f9153201 parent 7c8848e2 files · +31 −2Browse files

Unified · Split

2 files
  1. apps/web/src/markdown-links.test.ts +25 −0
  2. apps/web/src/markdown-links.ts +6 −2
apps/web/src/markdown-links.test.ts+25−0
@@ -273,3 +273,28 @@ describe("resolveInlineCodeFileLinkMeta", () => { · 272 unmodified lines
273 expect(resolveInlineCodeFileLinkMeta(".plans/worktree-management-v1.md")).toBeNull();273 expect(resolveInlineCodeFileLinkMeta(".plans/worktree-management-v1.md")).toBeNull();
274 });274 });
275});275});
276
277describe("directory paths with a trailing separator", () => {
278 it("keeps the final segment for a POSIX directory path", () => {
279 expect(resolveMarkdownFileLinkMeta("/tmp/favicons/", "/repo/project")).toMatchObject({
280 basename: "favicons",
281 });
282 });
283
284 it("keeps the final segment for a Windows directory path", () => {
285 expect(
286 resolveMarkdownFileLinkMeta("C:\\Users\\kelchm\\.claude\\", "/repo/project"),
287 ).toMatchObject({ basename: ".claude" });
288 });
289
290 it("matches the label of the same path without a trailing separator", () => {
291 const withSlash = resolveMarkdownFileLinkMeta("/tmp/favicons/", "/repo/project");
292 const withoutSlash = resolveMarkdownFileLinkMeta("/tmp/favicons", "/repo/project");
293 expect(withSlash?.basename).toBe(withoutSlash?.basename);
294 });
295
296 it("does not produce an empty label for the filesystem root", () => {
297 const meta = resolveMarkdownFileLinkMeta("/tmp/", "/repo/project");
298 expect(meta?.basename).not.toBe("");
299 });
300});
apps/web/src/markdown-links.ts+6−2
@@ -359,8 +359,12 @@ export function resolveInlineCodeFileLinkMeta( · 358 unmodified lines
359}359}
360 360
361function basenameOfPath(path: string): string {361function basenameOfPath(path: string): string {
362 const separatorIndex = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));362 // A trailing separator is a valid way to write a directory, so trim it before
363 return separatorIndex >= 0 ? path.slice(separatorIndex + 1) : path;363 // taking the final segment. Without this the segment reads as empty and the
364 // chip renders with no label at all.
365 const trimmed = path.replace(/[/\\]+$/, "") || path;
366 const separatorIndex = Math.max(trimmed.lastIndexOf("/"), trimmed.lastIndexOf("\\"));
367 return separatorIndex >= 0 ? trimmed.slice(separatorIndex + 1) : trimmed;
364}368}
365 369
366function workspaceRelativePath(path: string, workspaceRoot: string | undefined): string | null {370function workspaceRelativePath(path: string, workspaceRoot: string | undefined): string | null {