Skip to content

Commit e64a878

Browse files
authored
fix(auto-nav-sidebar): exclude route.exclude files from auto-generated sidebars and place index.md at the top (#3171)
1 parent 4d01488 commit e64a878

File tree

11 files changed

+166
-17
lines changed

11 files changed

+166
-17
lines changed

e2e/fixtures/auto-nav-sidebar-issue-1682/index.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ test.describe('Auto nav and sidebar dir issue-1682', async () => {
2727
const sidebarTexts = await getSidebarTexts(page);
2828
expect(sidebarTexts.length).toBe(3);
2929
expect(sidebarTexts.join(',')).toEqual(
30-
['Second sub-directory', 'test', 'First sub-directory'].join(','),
30+
['First sub-directory', 'Second sub-directory', 'test'].join(','),
3131
);
3232
});
3333
});

e2e/fixtures/auto-nav-sidebar-no-meta/index.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ test.describe('Auto nav and sidebar test', async () => {
2424

2525
const sidebarTexts = await getSidebarTexts(page);
2626
expect(sidebarTexts).toEqual([
27+
'HomePage',
2728
'API',
2829
'plugin',
2930
'Plugin a',
@@ -34,7 +35,6 @@ test.describe('Auto nav and sidebar test', async () => {
3435
'Build config',
3536
'Front matter config',
3637
'Theme config',
37-
'HomePage',
3838
]);
3939
});
4040

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{ "text": "Guide", "link": "/guide/", "activeMatch": "^/guide/" }]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
["a", "b", "excluded-file"]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
title: Page a
3+
---
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
title: Page b
3+
---
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
title: Excluded
3+
---
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Button

packages/core/src/node/auto-nav-sidebar/normalize.ts

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { logger } from '@rspress/shared/logger';
1212
import picocolors from 'picocolors';
1313
import { PUBLIC_DIR } from '../constants';
1414
import { absolutePathToRoutePath, addRoutePrefix } from '../route/RoutePage';
15+
import { RouteService } from '../route/RouteService';
1516
import { createError } from '../utils';
1617
import type {
1718
CustomLinkMeta,
@@ -43,7 +44,16 @@ async function fsDirToMetaItems(
4344
): Promise<SideMetaItem[]> {
4445
let subItems: string[];
4546
try {
46-
subItems = await readdir(workDir);
47+
subItems = (await readdir(workDir)).sort((a, b) => {
48+
// 1. index.md or index.mdx should be placed at the top of the sidebar
49+
const aIsIndex = a.replace(/\.[^/.]+$/, '') === 'index';
50+
const bIsIndex = b.replace(/\.[^/.]+$/, '') === 'index';
51+
if (aIsIndex !== bIsIndex) {
52+
return aIsIndex ? -1 : 1;
53+
}
54+
// 2. Dictionary order
55+
return a.localeCompare(b);
56+
});
4757
} catch (e) {
4858
const metaFilePath = join(workDir, '_meta.json');
4959

@@ -100,6 +110,7 @@ async function metaItemToSidebarItem(
100110
): Promise<
101111
| (SidebarItem | SidebarGroup | SidebarDivider | SidebarSectionHeader)
102112
| (SidebarItem | SidebarGroup | SidebarDivider | SidebarSectionHeader)[]
113+
| null
103114
> {
104115
if (typeof metaItem === 'string') {
105116
return metaFileItemToSidebarItem(
@@ -123,7 +134,7 @@ async function metaItemToSidebarItem(
123134
}
124135

125136
if (type === 'dir') {
126-
return metaDirItemToSidebarItem(
137+
const group = await metaDirItemToSidebarItem(
127138
metaItem,
128139
workDir,
129140
docsDir,
@@ -132,17 +143,26 @@ async function metaItemToSidebarItem(
132143
mdFileSet,
133144
false,
134145
);
146+
if (group.items.length === 0 && !group.link) {
147+
return null;
148+
}
149+
return group;
135150
}
136151

137152
if (type === 'dir-section-header') {
138-
return metaDirSectionHeaderItemToSidebarItem(
153+
const items = await metaDirSectionHeaderItemToSidebarItem(
139154
metaItem,
140155
workDir,
141156
docsDir,
142157
extensions,
143158
metaFileSet,
144159
mdFileSet,
145160
);
161+
// If only the section header remains (no child items), prune it
162+
if (items.length <= 1) {
163+
return null;
164+
}
165+
return items;
146166
}
147167

148168
if (type === 'custom-link') {
@@ -184,7 +204,7 @@ async function metaFileItemToSidebarItem(
184204
docsDir: string,
185205
extensions: string[],
186206
mdFileSet: Set<string>,
187-
): Promise<SidebarItem> {
207+
): Promise<SidebarItem | null> {
188208
let metaItem: FileSideMeta | null = null;
189209
if (typeof metaItemRaw === 'string') {
190210
metaItem = {
@@ -218,6 +238,10 @@ async function metaFileItemToSidebarItem(
218238
}
219239

220240
const link = absolutePathToRoutePath(absolutePathWithExt, docsDir);
241+
const routeService = RouteService.getInstance();
242+
if (routeService?.isExistRoute && !routeService.isExistRoute(link)) {
243+
return null;
244+
}
221245
const info = await extractInfoFromFrontmatterWithAbsolutePath(
222246
absolutePathWithExt,
223247
docsDir,
@@ -294,7 +318,12 @@ async function metaDirItemToSidebarItem(
294318
),
295319
),
296320
);
297-
return items.flat();
321+
return items.flat().filter(Boolean) as (
322+
| SidebarItem
323+
| SidebarGroup
324+
| SidebarDivider
325+
| SidebarSectionHeader
326+
)[];
298327
}
299328

300329
try {
@@ -310,6 +339,10 @@ async function metaDirItemToSidebarItem(
310339
mdFileSet,
311340
);
312341

342+
if (!sameNameFile) {
343+
throw new Error(`Excluded route: ${name}`);
344+
}
345+
313346
const { link, text, _fileKey, context, overviewHeaders, tag } =
314347
sameNameFile;
315348
return {
@@ -357,6 +390,18 @@ async function metaDirItemToSidebarItem(
357390
mdFileSet,
358391
);
359392

393+
if (!indexFile) {
394+
return {
395+
text: label || name,
396+
collapsible,
397+
collapsed,
398+
items: await getItems(),
399+
overviewHeaders: metaJsonOverviewHeaders,
400+
context: metaJsonContext,
401+
_fileKey: getFileKey(dirAbsolutePath, docsDir),
402+
} satisfies SidebarGroup;
403+
}
404+
360405
const { link, text, _fileKey, context, overviewHeaders, tag } = indexFile;
361406
return {
362407
text: label || text || name,

0 commit comments

Comments
 (0)