diff --git a/scm-ui/ui-components/src/MarkdownLinkRenderer.test.tsx b/scm-ui/ui-components/src/MarkdownLinkRenderer.test.tsx index 3ee5e3f188..719baa254c 100644 --- a/scm-ui/ui-components/src/MarkdownLinkRenderer.test.tsx +++ b/scm-ui/ui-components/src/MarkdownLinkRenderer.test.tsx @@ -57,11 +57,13 @@ describe("test isLinkWithProtocol", () => { expect(isLinkWithProtocol("urn:oasis:names:specification:docbook:dtd:xml:4.1.2")).toBe(true); expect(isLinkWithProtocol("about:config")).toBe(true); expect(isLinkWithProtocol("http://cloudogu.com")).toBe(true); + expect(isLinkWithProtocol("file:///srv/git/project.git")).toBe(true); + expect(isLinkWithProtocol("ssh://trillian@server/project.git")).toBe(true); }); it("should return false", () => { - expect(isExternalLink("some/path/link")).toBe(false); - expect(isExternalLink("/some/path/link")).toBe(false); - expect(isExternalLink("#some-anchor")).toBe(false); + expect(isLinkWithProtocol("some/path/link")).toBe(false); + expect(isLinkWithProtocol("/some/path/link")).toBe(false); + expect(isLinkWithProtocol("#some-anchor")).toBe(false); }); }); @@ -106,11 +108,21 @@ describe("test createLocalLink", () => { expect(localLink).toBe("/src/README.md"); }); + it("should resolve .. to / if we reached the end", () => { + const localLink = createLocalLink("/", "/index.md", "../../README.md"); + expect(localLink).toBe("/README.md"); + }); + it("should resolve . with in path", () => { const localLink = createLocalLink("/src", "/src/README.md", "./LICENSE.md"); expect(localLink).toBe("/src/LICENSE.md"); }); + it("should resolve . with the current directory", () => { + const localLink = createLocalLink("/", "/README.md", "././LICENSE.md"); + expect(localLink).toBe("/LICENSE.md"); + }); + it("should handle complex path", () => { const localLink = createLocalLink("/src", "/src/docs/installation/index.md", "./.././../docs/index.md"); expect(localLink).toBe("/src/docs/index.md"); diff --git a/scm-ui/ui-components/src/MarkdownLinkRenderer.tsx b/scm-ui/ui-components/src/MarkdownLinkRenderer.tsx index 2de0846f28..8ae1bc6135 100644 --- a/scm-ui/ui-components/src/MarkdownLinkRenderer.tsx +++ b/scm-ui/ui-components/src/MarkdownLinkRenderer.tsx @@ -59,14 +59,26 @@ const normalizePath = (path: string) => { stack.push(part) } } - return stack.join("/") + const normalizedPath = stack.join("/") + if (normalizedPath.startsWith("/")) { + return normalizedPath; + } + return "/" + normalizedPath; +}; + +const isAbsolute = (link: string) => { + return link.startsWith("/"); +}; + +const isSubDirectoryOf = (basePath: string, currentPath: string) => { + return currentPath.startsWith(basePath); }; export const createLocalLink = (basePath: string, currentPath: string, link: string) => { - if (link.startsWith("/")) { + if (isAbsolute(link)) { return join(basePath, link); } - if (!currentPath.startsWith(basePath)) { + if (!isSubDirectoryOf(basePath, currentPath)) { return join(basePath, link); } let path = currentPath;