diff --git a/src/util/relative-to-root-links.js b/src/util/relative-to-root-links.js index d5b3c73e..ee33c5e8 100644 --- a/src/util/relative-to-root-links.js +++ b/src/util/relative-to-root-links.js @@ -4,6 +4,10 @@ function removeMdExtension(path) { return path.replace(/\.md$/, ''); } +function removeTrailingIndex(path) { + return path.includes('#') ? path.replace(/\/index(?:\.md)?/, '/') : path.replace(/\/index$/, ''); +} + /** * Convert relative links in docs to relative but from the /docs root * @@ -25,7 +29,7 @@ function relativeToRootLinks(href, path = '', isIndexPage) { // rewrite ../../../release-#-#/docs/parent/some-path style urls to /docs/version/parent/some-path const overrideVersion = versionedUrl[1].split('-').join('.'); url = buildPathWithVersion(href.replace(/.*\/docs\/(.*)/, '/docs/$1'), overrideVersion); - return removeMdExtension(url); + return removeTrailingIndex(removeMdExtension(url)); } if (isIndexPage && relativeUrlRegex.test(url)) { @@ -41,13 +45,13 @@ function relativeToRootLinks(href, path = '', isIndexPage) { const slugParts = path.split('/').filter((p) => !!p); slugParts.splice(-1, 1, url.replace(relativeUrlRegex, '$2')); url = `/${slugParts.join('/')}`; - return removeMdExtension(url); + return removeTrailingIndex(removeMdExtension(url)); } if (multiLevelRelativeUrlRegex.test(url)) { // rewrite ../parent/some-path style urls to /docs/version?/parent/some-path url = buildPathWithVersion(url.replace(multiLevelRelativeUrlRegex, '/docs/$2')); - return removeMdExtension(url); + return removeTrailingIndex(removeMdExtension(url)); } return url; diff --git a/src/util/relative-to-root-links.test.ts b/src/util/relative-to-root-links.test.ts index f34ee1d0..32a6a693 100644 --- a/src/util/relative-to-root-links.test.ts +++ b/src/util/relative-to-root-links.test.ts @@ -23,6 +23,16 @@ it('transforms specific-version links', () => { expect(rootUrl).toEqual('/docs/6.5/api/csf'); }); +it('removes trailing index pages', () => { + const rootUrl = relativeToRootLinks('../writing-stories/index.md', '/docs/api/csf'); + expect(rootUrl).toEqual('/docs/writing-stories'); +}); + +it('retains URL fragment on trailing index pages', () => { + const rootUrl = relativeToRootLinks('../writing-stories/index.md#foo', '/docs/api/csf'); + expect(rootUrl).toEqual('/docs/writing-stories/#foo'); +}); + it('does not transform non-versioned upper-level links', () => { const rootUrl = relativeToRootLinks('../../foo/bar/README.md', '/docs/writing-stories/args'); expect(rootUrl).toEqual('../../foo/bar/README.md');