Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(sidebar): /api/index.html /api/index /api should show same sidebar #1578

Merged
merged 2 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions e2e/tests/auto-nav-sidebar-dir-convension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,51 @@ test.describe('Auto nav and sidebar dir convention', async () => {
);
expect(contexts3.join(',')).toEqual(['context-index-in-meta'].join(','));
});

test('/api/config/index.html /api/config/index /api/config should be the same page', async ({
page,
}) => {
async function getSidebarLength(): Promise<number> {
return (
(await page.$$(
`.rspress-sidebar .rspress-scrollbar > nav > section,
.rspress-sidebar .rspress-scrollbar > nav > a`,
)) ?? []
).length;
}

async function isMenuItemActive(): Promise<boolean> {
const activeMenuItem = await page.$(
'.rspress-sidebar-collapse[class*="menuItemActive"]',
);
const content = await activeMenuItem?.textContent();
return content === 'index md convention';
}
// /api/config/index.html
await page.goto(
`http://localhost:${appPort}/guide/index-md-convention/index.html`,
{
waitUntil: 'networkidle',
},
);
expect(await getSidebarLength()).toBe(7);
expect(await isMenuItemActive()).toBe(true);

// /api/config/index
await page.goto(
`http://localhost:${appPort}/guide/index-md-convention/index`,
{
waitUntil: 'networkidle',
},
);
expect(await getSidebarLength()).toBe(7);
expect(await isMenuItemActive()).toBe(true);

// /api/config
await page.goto(`http://localhost:${appPort}/guide/index-md-convention`, {
waitUntil: 'networkidle',
});
expect(await getSidebarLength()).toBe(7);
expect(await isMenuItemActive()).toBe(true);
});
});
5 changes: 3 additions & 2 deletions packages/theme-default/src/components/Sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,13 @@ export function Sidebar(props: Props) {
const removeLangPrefix = (path: string) => {
return path.replace(langRoutePrefix, '');
};
const activeMatcher = (path: string) =>
isActive(
const activeMatcher = (path: string) => {
return isActive(
removeBase(removeLangPrefix(pathname)),
removeLangPrefix(path),
true,
);
};
const preloadLink = (link: string) => {
const match = matchRoutes(routes, link);
if (match?.length) {
Expand Down
6 changes: 3 additions & 3 deletions packages/theme-default/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import React from 'react';
import { NotFoundLayout } from './layout/NotFountLayout';
import { Layout } from './layout/Layout';
import { HomeLayout } from './layout/HomeLayout';
import { DocLayout } from './layout/DocLayout';
import { HomeLayout } from './layout/HomeLayout';
import { Layout } from './layout/Layout';
import { NotFoundLayout } from './layout/NotFountLayout';
import { setup } from './logic';

export default {
Expand Down
45 changes: 34 additions & 11 deletions packages/theme-default/src/logic/useSidebarData.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { isEqualPath, useLocation, withBase } from '@rspress/runtime';
import {
type NormalizedSidebarGroup,
type SidebarItem,
type NormalizedSidebar,
type NormalizedSidebarGroup,
type SidebarDivider,
type SidebarItem,
addTrailingSlash,
} from '@rspress/shared';
import { useEffect, useState } from 'react';
import { useLocation, withBase, isEqualPath } from '@rspress/runtime';
import { useLocaleSiteData } from './useLocaleSiteData';

interface SidebarData {
Expand Down Expand Up @@ -65,6 +65,7 @@ export const getSidebarGroupData = (
currentPathname.startsWith(
// https://github.com/web-infra-dev/rspress/issues/360
// Ensure the other group name ends with `/` to avoid some unexpected results, for example, `/react-native` will match `/react`, that's not what we want
// FIXME: should parse url instead of add trailing slash
addTrailingSlash(withBase(otherGroupName)),
)
) {
Expand All @@ -74,20 +75,42 @@ export const getSidebarGroupData = (
}
}
}
const equalFunc = () =>
'link' in item &&
item.link !== '' &&
isEqualPath(withBase(item.link), currentPathname);

if ('items' in item) {
// If the current path is the same as the group link, return true
if (equalFunc()) {
const isLink = 'link' in item && item.link !== '';
const isDir = 'items' in item;

// 0. divider or section headers others return false

// 1. file link
if (!isDir && isLink) {
// 1.1 /api/config /api/config.html
if (isEqualPath(withBase(item.link), currentPathname)) {
return true;
}
// 1.2 /api/config/index /api/config/index.html
if (
currentPathname.includes('index') &&
isEqualPath(`${item.link}/index`, currentPathname)
) {
return true;
}
}

// 2. dir
if (isDir) {
// 2.1 dir link (index convention)
if (
isLink &&
(isEqualPath(withBase(item.link), currentPathname) ||
isEqualPath(withBase(`${item.link}/index`), currentPathname))
) {
return true;
}
// 2.2 dir recursive
return item.items.some(i => match(i));
}

return equalFunc();
return false;
};

return match(group);
Expand Down
13 changes: 8 additions & 5 deletions packages/theme-default/src/logic/utils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import React from 'react';
import htmr from 'htmr';
import { parseDocument } from 'htmlparser2';
import { isEqualPath } from '@rspress/runtime';
import { parseDocument } from 'htmlparser2';
import htmr from 'htmr';
import { isNumber } from 'lodash-es';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import React from 'react';

export function isActive(
currentPath: string,
Expand All @@ -14,7 +14,10 @@ export function isActive(
return false;
}
if (strict) {
return isEqualPath(currentPath, targetLink);
return (
isEqualPath(currentPath, targetLink) ||
isEqualPath(currentPath, `${targetLink}/index`)
);
}

return (
Expand Down
Loading