diff --git a/src/utils/docs-redirects.ts b/src/utils/docs-redirects.ts index 3565086ff..4ab83b43b 100644 --- a/src/utils/docs-redirects.ts +++ b/src/utils/docs-redirects.ts @@ -38,16 +38,19 @@ export function resolveDocsPathRedirect({ return { type: 'not-found' } } + // Manifest paths already have one trailing /index removed. Preserve the + // requested path for loading so nested index/index files stay distinct. + const canonicalRequestedPath = canonicalizeDocsPath(requestedPath) const knownPaths = new Set(manifest.paths.map(normalizeManifestPath)) - if (knownPaths.has(requestedPath)) { + if (knownPaths.has(canonicalRequestedPath)) { return { type: 'render', docsPath: requestedPath } } const redirectFromTarget = getRedirectTarget({ knownPaths, manifest, - requestedPath, + requestedPath: canonicalRequestedPath, }) if (redirectFromTarget !== null) { @@ -58,7 +61,7 @@ export function resolveDocsPathRedirect({ defaultDocs, frameworks, knownPaths, - requestedPath, + requestedPath: canonicalRequestedPath, }) if (frameworkRedirectTarget !== null) { @@ -67,7 +70,7 @@ export function resolveDocsPathRedirect({ const sectionIndexRedirectTarget = getSectionIndexRedirectTarget({ knownPaths, - requestedPath, + requestedPath: canonicalRequestedPath, }) if (sectionIndexRedirectTarget !== null) { @@ -87,8 +90,10 @@ export function docsManifestHasPath( return false } + const canonicalPath = canonicalizeDocsPath(normalizedPath) + return manifest.paths.some( - (path) => normalizeManifestPath(path) === normalizedPath, + (path) => normalizeManifestPath(path) === canonicalPath, ) } @@ -220,10 +225,17 @@ function getSectionIndexRedirectTarget(opts: { } function normalizeManifestPath(path: string) { - return removeLeadingSlash(path.trim()) - .replace(/\.md$/, '') - .replace(/\/index$/, '') - .replace(/\/+$/g, '') + const normalizedPath = removeLeadingSlash(path.trim()).replace(/\/+$/g, '') + + if (normalizedPath.endsWith('.md')) { + return normalizedPath.replace(/\.md$/, '').replace(/\/index$/, '') + } + + return normalizedPath +} + +function canonicalizeDocsPath(path: string) { + return path.replace(/\/index$/, '') } function normalizeDocsPath(path: string | null | undefined) { diff --git a/tests/docs-redirects.test.ts b/tests/docs-redirects.test.ts index 77a907ca7..305687799 100644 --- a/tests/docs-redirects.test.ts +++ b/tests/docs-redirects.test.ts @@ -55,6 +55,23 @@ function assertRedirectsTo(opts: { ) } +function assertRenders(opts: { + defaultDocs: string + docsPath: string + frameworks: Array + manifest: DocsRedirectManifest +}) { + assert.deepEqual( + resolveDocsPathRedirect({ + defaultDocs: opts.defaultDocs, + docsPath: opts.docsPath, + frameworks: opts.frameworks, + manifest: opts.manifest, + }), + { type: 'render', docsPath: opts.docsPath }, + ) +} + function assertNotFound(opts: { defaultDocs: string docsPath: string @@ -160,6 +177,50 @@ assertNotFound({ manifest: manifestWithPaths(['overview', 'framework/react/overview']), }) +const typedocManifest = manifestWithPaths([ + 'overview', + 'reference', + 'reference/index', + 'reference/index/type-aliases/DebugOptions', + 'framework/react/reference', + 'framework/react/reference/index', +]) + +assertRenders({ + defaultDocs: 'overview', + docsPath: 'reference/index', + frameworks: ['react'], + manifest: typedocManifest, +}) + +assertRenders({ + defaultDocs: 'overview', + docsPath: 'reference/index/index', + frameworks: ['react'], + manifest: typedocManifest, +}) + +assertRenders({ + defaultDocs: 'overview', + docsPath: 'reference/index/type-aliases/DebugOptions', + frameworks: ['react'], + manifest: typedocManifest, +}) + +assertRenders({ + defaultDocs: 'overview', + docsPath: 'framework/react/reference/index', + frameworks: ['react'], + manifest: typedocManifest, +}) + +assertRenders({ + defaultDocs: 'overview', + docsPath: 'framework/react/reference/index/index', + frameworks: ['react'], + manifest: typedocManifest, +}) + assertRedirectsTo({ defaultDocs: 'overview', docsPath: 'react/overview', @@ -225,6 +286,14 @@ assert.equal( true, ) +assert.equal( + docsManifestHasPath( + manifestWithPaths(['reference/index']), + 'reference/index/index', + ), + true, +) + assert.equal( docsManifestHasPath( manifestWithPaths(['guides/queries.md']), diff --git a/tests/docs-route-smoke.test.ts b/tests/docs-route-smoke.test.ts index 03807ab02..0f0806c21 100644 --- a/tests/docs-route-smoke.test.ts +++ b/tests/docs-route-smoke.test.ts @@ -56,6 +56,17 @@ test( }) } + if (library.id === 'table') { + paths.push({ + path: '/table/latest/docs/reference/index/index', + expected: 'ok', + }) + paths.push({ + path: '/table/latest/docs/framework/react/reference/index/index', + expected: 'ok', + }) + } + return paths })