Skip to content

Commit f35cb79

Browse files
authored
Fix nested TypeDoc index routes (#1160)
1 parent 93de689 commit f35cb79

3 files changed

Lines changed: 101 additions & 9 deletions

File tree

src/utils/docs-redirects.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,19 @@ export function resolveDocsPathRedirect({
3838
return { type: 'not-found' }
3939
}
4040

41+
// Manifest paths already have one trailing /index removed. Preserve the
42+
// requested path for loading so nested index/index files stay distinct.
43+
const canonicalRequestedPath = canonicalizeDocsPath(requestedPath)
4144
const knownPaths = new Set(manifest.paths.map(normalizeManifestPath))
4245

43-
if (knownPaths.has(requestedPath)) {
46+
if (knownPaths.has(canonicalRequestedPath)) {
4447
return { type: 'render', docsPath: requestedPath }
4548
}
4649

4750
const redirectFromTarget = getRedirectTarget({
4851
knownPaths,
4952
manifest,
50-
requestedPath,
53+
requestedPath: canonicalRequestedPath,
5154
})
5255

5356
if (redirectFromTarget !== null) {
@@ -58,7 +61,7 @@ export function resolveDocsPathRedirect({
5861
defaultDocs,
5962
frameworks,
6063
knownPaths,
61-
requestedPath,
64+
requestedPath: canonicalRequestedPath,
6265
})
6366

6467
if (frameworkRedirectTarget !== null) {
@@ -67,7 +70,7 @@ export function resolveDocsPathRedirect({
6770

6871
const sectionIndexRedirectTarget = getSectionIndexRedirectTarget({
6972
knownPaths,
70-
requestedPath,
73+
requestedPath: canonicalRequestedPath,
7174
})
7275

7376
if (sectionIndexRedirectTarget !== null) {
@@ -87,8 +90,10 @@ export function docsManifestHasPath(
8790
return false
8891
}
8992

93+
const canonicalPath = canonicalizeDocsPath(normalizedPath)
94+
9095
return manifest.paths.some(
91-
(path) => normalizeManifestPath(path) === normalizedPath,
96+
(path) => normalizeManifestPath(path) === canonicalPath,
9297
)
9398
}
9499

@@ -220,10 +225,17 @@ function getSectionIndexRedirectTarget(opts: {
220225
}
221226

222227
function normalizeManifestPath(path: string) {
223-
return removeLeadingSlash(path.trim())
224-
.replace(/\.md$/, '')
225-
.replace(/\/index$/, '')
226-
.replace(/\/+$/g, '')
228+
const normalizedPath = removeLeadingSlash(path.trim()).replace(/\/+$/g, '')
229+
230+
if (normalizedPath.endsWith('.md')) {
231+
return normalizedPath.replace(/\.md$/, '').replace(/\/index$/, '')
232+
}
233+
234+
return normalizedPath
235+
}
236+
237+
function canonicalizeDocsPath(path: string) {
238+
return path.replace(/\/index$/, '')
227239
}
228240

229241
function normalizeDocsPath(path: string | null | undefined) {

tests/docs-redirects.test.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,23 @@ function assertRedirectsTo(opts: {
5555
)
5656
}
5757

58+
function assertRenders(opts: {
59+
defaultDocs: string
60+
docsPath: string
61+
frameworks: Array<string>
62+
manifest: DocsRedirectManifest
63+
}) {
64+
assert.deepEqual(
65+
resolveDocsPathRedirect({
66+
defaultDocs: opts.defaultDocs,
67+
docsPath: opts.docsPath,
68+
frameworks: opts.frameworks,
69+
manifest: opts.manifest,
70+
}),
71+
{ type: 'render', docsPath: opts.docsPath },
72+
)
73+
}
74+
5875
function assertNotFound(opts: {
5976
defaultDocs: string
6077
docsPath: string
@@ -160,6 +177,50 @@ assertNotFound({
160177
manifest: manifestWithPaths(['overview', 'framework/react/overview']),
161178
})
162179

180+
const typedocManifest = manifestWithPaths([
181+
'overview',
182+
'reference',
183+
'reference/index',
184+
'reference/index/type-aliases/DebugOptions',
185+
'framework/react/reference',
186+
'framework/react/reference/index',
187+
])
188+
189+
assertRenders({
190+
defaultDocs: 'overview',
191+
docsPath: 'reference/index',
192+
frameworks: ['react'],
193+
manifest: typedocManifest,
194+
})
195+
196+
assertRenders({
197+
defaultDocs: 'overview',
198+
docsPath: 'reference/index/index',
199+
frameworks: ['react'],
200+
manifest: typedocManifest,
201+
})
202+
203+
assertRenders({
204+
defaultDocs: 'overview',
205+
docsPath: 'reference/index/type-aliases/DebugOptions',
206+
frameworks: ['react'],
207+
manifest: typedocManifest,
208+
})
209+
210+
assertRenders({
211+
defaultDocs: 'overview',
212+
docsPath: 'framework/react/reference/index',
213+
frameworks: ['react'],
214+
manifest: typedocManifest,
215+
})
216+
217+
assertRenders({
218+
defaultDocs: 'overview',
219+
docsPath: 'framework/react/reference/index/index',
220+
frameworks: ['react'],
221+
manifest: typedocManifest,
222+
})
223+
163224
assertRedirectsTo({
164225
defaultDocs: 'overview',
165226
docsPath: 'react/overview',
@@ -225,6 +286,14 @@ assert.equal(
225286
true,
226287
)
227288

289+
assert.equal(
290+
docsManifestHasPath(
291+
manifestWithPaths(['reference/index']),
292+
'reference/index/index',
293+
),
294+
true,
295+
)
296+
228297
assert.equal(
229298
docsManifestHasPath(
230299
manifestWithPaths(['guides/queries.md']),

tests/docs-route-smoke.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@ test(
5656
})
5757
}
5858

59+
if (library.id === 'table') {
60+
paths.push({
61+
path: '/table/latest/docs/reference/index/index',
62+
expected: 'ok',
63+
})
64+
paths.push({
65+
path: '/table/latest/docs/framework/react/reference/index/index',
66+
expected: 'ok',
67+
})
68+
}
69+
5970
return paths
6071
})
6172

0 commit comments

Comments
 (0)