From d7cfbec796e5e24d436e396320c5b32a1ee2ccc3 Mon Sep 17 00:00:00 2001 From: Shuvam Kumar <145355204+shuvamk@users.noreply.github.com> Date: Thu, 23 Jul 2026 19:26:09 +0530 Subject: [PATCH] fix(backlinks): keep truncateMiddle within maxLength (#134) --- .../backlinks/backlinksPageUtils.test.ts | 33 +++++++++++++++++++ .../features/backlinks/backlinksPageUtils.ts | 11 +++++-- 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 src/client/features/backlinks/backlinksPageUtils.test.ts diff --git a/src/client/features/backlinks/backlinksPageUtils.test.ts b/src/client/features/backlinks/backlinksPageUtils.test.ts new file mode 100644 index 0000000..74cc855 --- /dev/null +++ b/src/client/features/backlinks/backlinksPageUtils.test.ts @@ -0,0 +1,33 @@ +import { describe, expect, it } from "vitest"; +import { truncateMiddle } from "./backlinksPageUtils"; + +describe("truncateMiddle", () => { + it("returns the value unchanged when it already fits", () => { + expect(truncateMiddle("short", 10)).toBe("short"); + expect(truncateMiddle("exactly-ten", "exactly-ten".length)).toBe( + "exactly-ten", + ); + }); + + it("never returns a string longer than maxLength", () => { + const value = "/very/long/path/segment/that/keeps/going/here"; + for (let maxLength = 0; maxLength <= value.length; maxLength++) { + expect(truncateMiddle(value, maxLength).length).toBeLessThanOrEqual( + maxLength, + ); + } + }); + + it("keeps head and tail around a middle ellipsis", () => { + expect(truncateMiddle("abcdefghijklmno", 10)).toBe("abc...mno"); + expect(truncateMiddle("/very/long/path/segment/here", 12)).toBe( + "/ver...here", + ); + }); + + it("head-truncates when there is no room for both sides", () => { + expect(truncateMiddle("abcdefgh", 4)).toBe("a..."); + expect(truncateMiddle("abcdefgh", 3)).toBe("abc"); + expect(truncateMiddle("abcdefgh", 2)).toBe("ab"); + }); +}); diff --git a/src/client/features/backlinks/backlinksPageUtils.ts b/src/client/features/backlinks/backlinksPageUtils.ts index 94a3338..78b7b2b 100644 --- a/src/client/features/backlinks/backlinksPageUtils.ts +++ b/src/client/features/backlinks/backlinksPageUtils.ts @@ -114,8 +114,15 @@ export function extractUrlPath(url: string) { } } +const ELLIPSIS = "..."; + export function truncateMiddle(value: string, maxLength: number) { if (value.length <= maxLength) return value; - const sideLength = Math.floor((maxLength - 1) / 2); - return `${value.slice(0, sideLength)}...${value.slice(-sideLength)}`; + if (maxLength <= ELLIPSIS.length) + return value.slice(0, Math.max(maxLength, 0)); + const sideLength = Math.floor((maxLength - ELLIPSIS.length) / 2); + if (sideLength <= 0) { + return `${value.slice(0, maxLength - ELLIPSIS.length)}${ELLIPSIS}`; + } + return `${value.slice(0, sideLength)}${ELLIPSIS}${value.slice(-sideLength)}`; }