From e117ae1f0a2bea1927058db16b6ed20e6ae2be77 Mon Sep 17 00:00:00 2001 From: SoonIter Date: Wed, 13 Nov 2024 12:13:51 +0800 Subject: [PATCH 1/8] test: add test case first --- .../doc/_meta.json | 7 +++ .../doc/guide/_meta.json | 33 ++++++++++ .../doc/guide/index-in-meta/_meta.json | 1 + .../doc/guide/index-in-meta/index.md | 1 + .../doc/guide/index-md-convention/_meta.json | 1 + .../doc/guide/index-md-convention/index.md | 1 + .../doc/guide/index-mdx-convention/_meta.json | 1 + .../doc/guide/index-mdx-convention/index.mdx | 1 + .../doc/guide/index.md | 1 + .../doc/guide/same-name.mdx | 1 + .../doc/guide/same-name/_meta.json | 1 + .../doc/guide/single-md/index.md | 1 + .../doc/guide/single-mdx/index.mdx | 1 + .../doc/index.md | 1 + .../package.json | 16 +++++ .../rspress.config.ts | 6 ++ .../tsconfig.json | 5 ++ .../auto-nav-sidebar-dir-convension.test.ts | 63 +++++++++++++++++++ pnpm-lock.yaml | 10 +++ 19 files changed, 152 insertions(+) create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/doc/_meta.json create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/_meta.json create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-in-meta/_meta.json create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-in-meta/index.md create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-md-convention/_meta.json create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-md-convention/index.md create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-mdx-convention/_meta.json create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-mdx-convention/index.mdx create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index.md create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/same-name.mdx create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/same-name/_meta.json create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-md/index.md create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-mdx/index.mdx create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/doc/index.md create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/package.json create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/rspress.config.ts create mode 100644 e2e/fixtures/auto-nav-sidebar-dir-convention/tsconfig.json create mode 100644 e2e/tests/auto-nav-sidebar-dir-convension.test.ts diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/_meta.json b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/_meta.json new file mode 100644 index 000000000..9de6d0712 --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/_meta.json @@ -0,0 +1,7 @@ +[ + { + "text": "Guide", + "link": "/guide/", + "activeMatch": "/guide/" + } +] diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/_meta.json b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/_meta.json new file mode 100644 index 000000000..7bbbc39f6 --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/_meta.json @@ -0,0 +1,33 @@ +[ + "index", + { + "type": "dir", + "label": "index-md-convention", + "name": "index-md-convention" + }, + { + "type": "dir", + "label": "index-mdx-convention", + "name": "index-mdx-convention" + }, + { + "type": "dir", + "label": "same-name", + "name": "same-name" + }, + { + "type": "dir", + "label": "index-in-meta", + "name": "index-in-meta" + }, + { + "type": "dir", + "label": "single-md", + "name": "single-md" + }, + { + "type": "dir", + "label": "single-mdx", + "name": "single-mdx" + } +] diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-in-meta/_meta.json b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-in-meta/_meta.json new file mode 100644 index 000000000..a7d5eda49 --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-in-meta/_meta.json @@ -0,0 +1 @@ +["index"] diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-in-meta/index.md b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-in-meta/index.md new file mode 100644 index 000000000..28b9eb085 --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-in-meta/index.md @@ -0,0 +1 @@ +# index-in-meta inner Page diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-md-convention/_meta.json b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-md-convention/_meta.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-md-convention/_meta.json @@ -0,0 +1 @@ +[] diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-md-convention/index.md b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-md-convention/index.md new file mode 100644 index 000000000..2b3640d52 --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-md-convention/index.md @@ -0,0 +1 @@ +# index-md-convention inner Page diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-mdx-convention/_meta.json b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-mdx-convention/_meta.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-mdx-convention/_meta.json @@ -0,0 +1 @@ +[] diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-mdx-convention/index.mdx b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-mdx-convention/index.mdx new file mode 100644 index 000000000..2f9e4412f --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-mdx-convention/index.mdx @@ -0,0 +1 @@ +# index-mdx-convention inner Page diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index.md b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index.md new file mode 100644 index 000000000..645631686 --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index.md @@ -0,0 +1 @@ +# /guide Page diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/same-name.mdx b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/same-name.mdx new file mode 100644 index 000000000..03f9ccde5 --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/same-name.mdx @@ -0,0 +1 @@ +# same-name outer Page diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/same-name/_meta.json b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/same-name/_meta.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/same-name/_meta.json @@ -0,0 +1 @@ +[] diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-md/index.md b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-md/index.md new file mode 100644 index 000000000..ffd87095f --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-md/index.md @@ -0,0 +1 @@ +# single-md inner Page diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-mdx/index.mdx b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-mdx/index.mdx new file mode 100644 index 000000000..9bf7b59bf --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-mdx/index.mdx @@ -0,0 +1 @@ +# single-mdx inner Page diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/index.md b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/index.md new file mode 100644 index 000000000..29658341f --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/index.md @@ -0,0 +1 @@ +# Hello World diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/package.json b/e2e/fixtures/auto-nav-sidebar-dir-convention/package.json new file mode 100644 index 000000000..5d947154e --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/package.json @@ -0,0 +1,16 @@ +{ + "name": "@rspress-fixture/rspress-auto-nav-sidebar-dir-convention", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "rspress dev", + "build": "rspress build", + "preview": "rspress preview" + }, + "dependencies": { + "rspress": "workspace:*" + }, + "devDependencies": { + "@types/node": "^18.11.17" + } +} diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/rspress.config.ts b/e2e/fixtures/auto-nav-sidebar-dir-convention/rspress.config.ts new file mode 100644 index 000000000..0731c0907 --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/rspress.config.ts @@ -0,0 +1,6 @@ +import * as path from 'node:path'; +import { defineConfig } from 'rspress/config'; + +export default defineConfig({ + root: path.join(__dirname, 'doc'), +}); diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/tsconfig.json b/e2e/fixtures/auto-nav-sidebar-dir-convention/tsconfig.json new file mode 100644 index 000000000..986627de2 --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "jsx": "react" + } +} diff --git a/e2e/tests/auto-nav-sidebar-dir-convension.test.ts b/e2e/tests/auto-nav-sidebar-dir-convension.test.ts new file mode 100644 index 000000000..b1d9700be --- /dev/null +++ b/e2e/tests/auto-nav-sidebar-dir-convension.test.ts @@ -0,0 +1,63 @@ +import { expect, test } from '@playwright/test'; +import path from 'node:path'; +import { getPort, killProcess, runDevCommand } from '../utils/runCommands'; + +const fixtureDir = path.resolve(__dirname, '../fixtures'); + +test.describe('Auto nav and sidebar dir convention', async () => { + let appPort; + let app; + test.beforeAll(async () => { + const appDir = path.join(fixtureDir, 'auto-nav-sidebar-dir-convention'); + appPort = await getPort(); + app = await runDevCommand(appDir, appPort); + }); + + test.afterAll(async () => { + if (app) { + await killProcess(app); + } + }); + + test('Should render sidebar with index convention correctly', async ({ + page, + }) => { + await page.goto(`http://localhost:${appPort}/guide/`, { + waitUntil: 'networkidle', + }); + + // take the sidebar, properly a section or a tag + const sidebar = + (await page.$$( + `.rspress-sidebar .rspress-scrollbar > nav > section, + .rspress-sidebar .rspress-scrollbar > nav > a`, + )) ?? []; + expect(sidebar.length).toBe(7); + const sidebarTexts = await Promise.all( + sidebar.map(element => element.textContent()), + ); + expect(sidebarTexts.join(',')).toEqual( + [ + '/guide Page', + 'index-md-convention', + 'index-mdx-convention', + 'same-name', + 'index-in-metaindex-in-meta inner Page', // index-in-meta has the sub sidebar + 'single-mdsingle-md inner Page', // single-md has the sub sidebar + 'single-mdxsingle-mdx inner Page', // single-mdx has the sub sidebar + ].join(','), + ); + }); + + test('Should click the directory and navigate to the index page', async ({ + page, + }) => { + await page.goto(`http://localhost:${appPort}/guide/`, { + waitUntil: 'networkidle', + }); + await page.click('.rspress-scrollbar nav section div'); + expect(page.url()).toBe( + `http://localhost:${appPort}/guide/index-md-convention.html`, + ); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4e7826412..a0b45e0c0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -98,6 +98,16 @@ importers: specifier: ^18.11.17 version: 18.11.17 + e2e/fixtures/auto-nav-sidebar-dir-convension: + dependencies: + rspress: + specifier: workspace:* + version: link:../../../packages/cli + devDependencies: + '@types/node': + specifier: ^18.11.17 + version: 18.11.17 + e2e/fixtures/auto-nav-sidebar-no-meta: dependencies: rspress: From e244c910bbb60a62d110e1254bba11388076c633 Mon Sep 17 00:00:00 2001 From: SoonIter Date: Wed, 13 Nov 2024 12:19:10 +0800 Subject: [PATCH 2/8] chore: update lock --- pnpm-lock.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a0b45e0c0..07d3b437d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -98,7 +98,7 @@ importers: specifier: ^18.11.17 version: 18.11.17 - e2e/fixtures/auto-nav-sidebar-dir-convension: + e2e/fixtures/auto-nav-sidebar-dir-convention: dependencies: rspress: specifier: workspace:* From 4d8a7c3d7830a2c8a9fb40d88797a2844ef9543d Mon Sep 17 00:00:00 2001 From: SoonIter Date: Wed, 13 Nov 2024 15:14:40 +0800 Subject: [PATCH 3/8] chore: update snapshot --- .../doc/guide/index-in-meta/index.md | 4 ++ .../doc/guide/index-md-convention/index.md | 4 ++ .../doc/guide/index-mdx-convention/index.mdx | 4 ++ .../doc/guide/same-name.mdx | 4 ++ .../doc/guide/single-md/index.md | 4 ++ .../doc/guide/single-mdx/index.mdx | 4 ++ .../auto-nav-sidebar-dir-convension.test.ts | 56 +++++++++++++++++++ 7 files changed, 80 insertions(+) diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-in-meta/index.md b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-in-meta/index.md index 28b9eb085..0e5f7013e 100644 --- a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-in-meta/index.md +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-in-meta/index.md @@ -1 +1,5 @@ +--- +context: 'context-index-in-meta' +--- + # index-in-meta inner Page diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-md-convention/index.md b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-md-convention/index.md index 2b3640d52..07197dcdc 100644 --- a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-md-convention/index.md +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-md-convention/index.md @@ -1 +1,5 @@ +--- +context: 'context-index-md-convention' +--- + # index-md-convention inner Page diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-mdx-convention/index.mdx b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-mdx-convention/index.mdx index 2f9e4412f..01e66db74 100644 --- a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-mdx-convention/index.mdx +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/index-mdx-convention/index.mdx @@ -1 +1,5 @@ +--- +context: 'context-index-mdx-convention' +--- + # index-mdx-convention inner Page diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/same-name.mdx b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/same-name.mdx index 03f9ccde5..e5530103b 100644 --- a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/same-name.mdx +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/same-name.mdx @@ -1 +1,5 @@ +--- +context: 'context-same-name' +--- + # same-name outer Page diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-md/index.md b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-md/index.md index ffd87095f..7e59929bc 100644 --- a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-md/index.md +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-md/index.md @@ -1 +1,5 @@ +--- +context: 'context-single-md' +--- + # single-md inner Page diff --git a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-mdx/index.mdx b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-mdx/index.mdx index 9bf7b59bf..2de0e3fd5 100644 --- a/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-mdx/index.mdx +++ b/e2e/fixtures/auto-nav-sidebar-dir-convention/doc/guide/single-mdx/index.mdx @@ -1 +1,5 @@ +--- +context: 'context-single-mdx' +--- + # single-mdx inner Page diff --git a/e2e/tests/auto-nav-sidebar-dir-convension.test.ts b/e2e/tests/auto-nav-sidebar-dir-convension.test.ts index b1d9700be..bb1ee3a23 100644 --- a/e2e/tests/auto-nav-sidebar-dir-convension.test.ts +++ b/e2e/tests/auto-nav-sidebar-dir-convension.test.ts @@ -60,4 +60,60 @@ test.describe('Auto nav and sidebar dir convention', async () => { `http://localhost:${appPort}/guide/index-md-convention.html`, ); }); + + test('Should generate data-context in dir convention', async ({ page }) => { + await page.goto(`http://localhost:${appPort}/guide/`, { + waitUntil: 'networkidle', + }); + + const sidebarGroupSections = await page.$$('.rspress-sidebar-section'); + + // first level + const contexts1 = await page.evaluate( + sidebars => + sidebars?.map(sidebar => sidebar.getAttribute('data-context')), + sidebarGroupSections, + ); + expect(contexts1.join(',')).toEqual( + [ + 'context-index-md-convention', + 'context-index-mdx-convention', + 'context-same-name', + '', + '', + '', + ].join(','), + ); + + const sidebarGroupCollapses = await page.$$('.rspress-sidebar-collapse'); + const contexts2 = await page.evaluate( + sidebars => + sidebars?.map(sidebar => sidebar.getAttribute('data-context')), + sidebarGroupCollapses, + ); + expect(contexts2.join(',')).toEqual( + [ + 'context-index-md-convention', + 'context-index-mdx-convention', + 'context-same-name', + '', + '', + '', + ].join(','), + ); + + const sidebarGroupItems = await page.$$('.rspress-sidebar-item'); + const contexts3 = await page.evaluate( + sidebarGroupConfig => + sidebarGroupConfig?.map(sidebarItem => + sidebarItem.getAttribute('data-context'), + ), + sidebarGroupItems, + ); + expect(contexts3.toString()).toEqual( + '["context-index-in-meta", "context-single-md", "context-single-mdx"]', + ); + expect(contexts3?.[2]).toEqual('front-matter'); + expect(contexts3?.[3]).toEqual('config-build'); + }); }); From 20521d68cdd2858ba7a642f709406a66967cce60 Mon Sep 17 00:00:00 2001 From: SoonIter Date: Wed, 13 Nov 2024 17:29:20 +0800 Subject: [PATCH 4/8] chore: fix the custom-link --- .../auto-nav-sidebar/doc/api/_meta.json | 11 +++ .../auto-nav-sidebar/doc/api/link/_meta.json | 8 ++ .../auto-nav-sidebar/doc/guide/_meta.json | 3 +- .../auto-nav-sidebar-dir-convension.test.ts | 8 +- e2e/tests/auto-nav-sidebar.test.ts | 50 ++++++---- .../docs/en/guide/basic/auto-nav-sidebar.mdx | 11 +++ .../docs/zh/guide/basic/auto-nav-sidebar.mdx | 6 ++ packages/plugin-auto-nav-sidebar/src/utils.ts | 22 ++++- packages/plugin-auto-nav-sidebar/src/walk.ts | 91 +++++++++++++++---- packages/runtime/src/utils.ts | 10 +- .../src/components/Sidebar/SidebarGroup.tsx | 10 +- .../src/components/Sidebar/SidebarItem.tsx | 2 +- .../src/components/Sidebar/index.tsx | 36 +++++++- 13 files changed, 213 insertions(+), 55 deletions(-) create mode 100644 e2e/fixtures/auto-nav-sidebar/doc/api/link/_meta.json diff --git a/e2e/fixtures/auto-nav-sidebar/doc/api/_meta.json b/e2e/fixtures/auto-nav-sidebar/doc/api/_meta.json index de07e7679..f3b6b54cb 100644 --- a/e2e/fixtures/auto-nav-sidebar/doc/api/_meta.json +++ b/e2e/fixtures/auto-nav-sidebar/doc/api/_meta.json @@ -16,6 +16,17 @@ "label": "Client API", "context": "client-api" }, + { + "type": "custom-link", + "label": "Rspack Official Docsite", + "link": "https://rspack.dev/", + "context": "rspack-official-docsite-custom-link" + }, + { + "type": "dir", + "name": "link", + "label": "Link" + }, "commands", "single-page" ] diff --git a/e2e/fixtures/auto-nav-sidebar/doc/api/link/_meta.json b/e2e/fixtures/auto-nav-sidebar/doc/api/link/_meta.json new file mode 100644 index 000000000..6763180bd --- /dev/null +++ b/e2e/fixtures/auto-nav-sidebar/doc/api/link/_meta.json @@ -0,0 +1,8 @@ +[ + { + "type": "custom-link", + "label": "Inner SideBar Rspack Official Docsite", + "link": "https://rspack.dev/", + "context": "rspack-official-docsite-custom-link" + } +] diff --git a/e2e/fixtures/auto-nav-sidebar/doc/guide/_meta.json b/e2e/fixtures/auto-nav-sidebar/doc/guide/_meta.json index 9aa97c7e5..1f9d22260 100644 --- a/e2e/fixtures/auto-nav-sidebar/doc/guide/_meta.json +++ b/e2e/fixtures/auto-nav-sidebar/doc/guide/_meta.json @@ -3,6 +3,7 @@ { "type": "dir", "name": "advanced", - "label": "Advanced" + "label": "Advanced", + "context": "advanced-dir" } ] diff --git a/e2e/tests/auto-nav-sidebar-dir-convension.test.ts b/e2e/tests/auto-nav-sidebar-dir-convension.test.ts index bb1ee3a23..449c181f0 100644 --- a/e2e/tests/auto-nav-sidebar-dir-convension.test.ts +++ b/e2e/tests/auto-nav-sidebar-dir-convension.test.ts @@ -110,10 +110,10 @@ test.describe('Auto nav and sidebar dir convention', async () => { ), sidebarGroupItems, ); - expect(contexts3.toString()).toEqual( - '["context-index-in-meta", "context-single-md", "context-single-mdx"]', + expect(contexts3.join(',')).toEqual( + ['context-index-in-meta', 'context-single-md', 'context-single-mdx'].join( + ',', + ), ); - expect(contexts3?.[2]).toEqual('front-matter'); - expect(contexts3?.[3]).toEqual('config-build'); }); }); diff --git a/e2e/tests/auto-nav-sidebar.test.ts b/e2e/tests/auto-nav-sidebar.test.ts index b260647da..2d740439d 100644 --- a/e2e/tests/auto-nav-sidebar.test.ts +++ b/e2e/tests/auto-nav-sidebar.test.ts @@ -1,4 +1,4 @@ -import { expect, test } from '@playwright/test'; +import { type ElementHandle, expect, test } from '@playwright/test'; import path from 'node:path'; import { getPort, killProcess, runDevCommand } from '../utils/runCommands'; import { getNavbar, getSidebar } from '../utils/getSideBar'; @@ -176,35 +176,47 @@ test.describe('Auto nav and sidebar test', async () => { waitUntil: 'networkidle', }); + function getDataContextFromElements( + elements: ElementHandle[], + ) { + return page.evaluate( + sidebars => + sidebars?.map(sidebar => sidebar.getAttribute('data-context')), + elements, + ); + } + const sidebarGroupSections = await page.$$('.rspress-sidebar-section'); - const contexts1 = await page.evaluate( - sidebars => - sidebars?.map(sidebar => sidebar.getAttribute('data-context')), - sidebarGroupSections, - ); - expect(contexts1.join(',')).toEqual( - ['config', null, 'client-api'].join(','), + const c1 = await getDataContextFromElements(sidebarGroupSections); + expect(c1.join(',')).toEqual( + ['config', null, 'client-api', null].join(','), ); const sidebarGroupCollapses = await page.$$('.rspress-sidebar-collapse'); - const contexts2 = await page.evaluate( + const c2 = await page.evaluate( sidebars => sidebars?.map(sidebar => sidebar.getAttribute('data-context')), sidebarGroupCollapses, ); - expect(contexts2.join(',')).toEqual( - ['config', null, 'client-api'].join(','), + expect(c2.join(',')).toEqual( + ['config', null, 'client-api', null].join(','), ); const sidebarGroupItems = await page.$$('.rspress-sidebar-item'); - const contexts3 = await page.evaluate( - sidebarGroupConfig => - sidebarGroupConfig?.map(sidebarItem => - sidebarItem.getAttribute('data-context'), - ), - sidebarGroupItems, + const c3 = await getDataContextFromElements(sidebarGroupItems); + expect(c3?.[2]).toEqual('front-matter'); + expect(c3?.[3]).toEqual('config-build'); + + // custom link should work + const customLinkItems = await page.$$( + '[data-context="rspack-official-docsite-custom-link"]', + ); + const c4 = await Promise.all(customLinkItems.map(i => i.textContent())); + + expect(c4.join(',')).toEqual( + ['Rspack Official Docsite', 'Inner SideBar Rspack Official Docsite'].join( + ',', + ), ); - expect(contexts3?.[2]).toEqual('front-matter'); - expect(contexts3?.[3]).toEqual('config-build'); }); }); diff --git a/packages/document/docs/en/guide/basic/auto-nav-sidebar.mdx b/packages/document/docs/en/guide/basic/auto-nav-sidebar.mdx index a215be9ad..43071bcb4 100644 --- a/packages/document/docs/en/guide/basic/auto-nav-sidebar.mdx +++ b/packages/document/docs/en/guide/basic/auto-nav-sidebar.mdx @@ -87,6 +87,17 @@ export type SideMetaItem = | { type: 'divider'; dashed?: boolean; + } + | { + type: 'section-header'; + label: string; + tag?: string; + } + | { + type: 'custom-link'; + label: string; + link: string; + context?: string; }; ``` diff --git a/packages/document/docs/zh/guide/basic/auto-nav-sidebar.mdx b/packages/document/docs/zh/guide/basic/auto-nav-sidebar.mdx index 3e68ace04..825ed5175 100644 --- a/packages/document/docs/zh/guide/basic/auto-nav-sidebar.mdx +++ b/packages/document/docs/zh/guide/basic/auto-nav-sidebar.mdx @@ -92,6 +92,12 @@ export type SideMetaItem = type: 'section-header'; label: string; tag?: string; + } + | { + type: 'custom-link'; + label: string; + link: string; + context: string; }; ``` diff --git a/packages/plugin-auto-nav-sidebar/src/utils.ts b/packages/plugin-auto-nav-sidebar/src/utils.ts index fc64f7bbe..8bddd1e5a 100644 --- a/packages/plugin-auto-nav-sidebar/src/utils.ts +++ b/packages/plugin-auto-nav-sidebar/src/utils.ts @@ -4,7 +4,10 @@ import type { NavItem, Sidebar } from '@rspress/shared'; import { logger } from '@rspress/shared/logger'; import { loadFrontMatter } from '@rspress/shared/node-utils'; -export async function detectFilePath(rawPath: string, extensions: string[]) { +export async function detectFilePath( + rawPath: string, + extensions: string[], +): Promise { // The params doesn't have extension name, so we need to try to find the file with the extension name. let realPath: string | undefined = rawPath; const fileExtname = path.extname(rawPath); @@ -50,13 +53,26 @@ export async function extractInfoFromFrontmatter( context: undefined, }; } + return { + ...(await extractInfoFromFrontmatterWithRealPath(realPath, rootDir)), + realPath, + }; +} + +export async function extractInfoFromFrontmatterWithRealPath( + realPath: string, + rootDir: string, +): Promise<{ + title: string; + overviewHeaders: string | undefined; + context: string | undefined; +}> { const content = await fs.readFile(realPath, 'utf-8'); const fileNameWithoutExt = path.basename(realPath, path.extname(realPath)); const h1RegExp = /^#\s+(.*)$/m; const match = content.match(h1RegExp); - const { frontmatter } = loadFrontMatter(content, filePath, rootDir); + const { frontmatter } = loadFrontMatter(content, realPath, rootDir); return { - realPath, title: frontmatter.title || match?.[1] || fileNameWithoutExt, overviewHeaders: frontmatter.overviewHeaders, context: frontmatter.context, diff --git a/packages/plugin-auto-nav-sidebar/src/walk.ts b/packages/plugin-auto-nav-sidebar/src/walk.ts index c82e77851..005eee256 100644 --- a/packages/plugin-auto-nav-sidebar/src/walk.ts +++ b/packages/plugin-auto-nav-sidebar/src/walk.ts @@ -1,4 +1,4 @@ -import path from 'node:path'; +import path, { join } from 'node:path'; import fs from '@rspress/shared/fs-extra'; import { type NavItem, @@ -12,16 +12,28 @@ import { type SidebarSectionHeader, } from '@rspress/shared'; import type { NavMeta, SideMeta } from './type'; -import { detectFilePath, extractInfoFromFrontmatter } from './utils'; +import { + detectFilePath, + extractInfoFromFrontmatter, + extractInfoFromFrontmatterWithRealPath, +} from './utils'; import { logger } from '@rspress/shared/logger'; +function getHmrFileKey(realPath: string | undefined, docsDir: string) { + return realPath + ? path.relative(docsDir, realPath).replace(/\.mdx?$/, '') + : ''; +} + export async function scanSideMeta( workDir: string, rootDir: string, docsDir: string, routePrefix: string, extensions: string[], -) { +): Promise< + (SidebarGroup | SidebarItem | SidebarDivider | SidebarSectionHeader)[] +> { if (!(await fs.exists(workDir))) { logger.error( '[plugin-auto-nav-sidebar]', @@ -101,7 +113,7 @@ export async function scanSideMeta( )[] = await Promise.all( sideMeta.map(async metaItem => { if (typeof metaItem === 'string') { - const { title, overviewHeaders, context } = + const { title, overviewHeaders, context, realPath } = await extractInfoFromFrontmatter( path.resolve(workDir, metaItem), rootDir, @@ -111,10 +123,11 @@ export async function scanSideMeta( return { text: title, link: addRoutePrefix(pureLink), + // FIXME: overviewHeaders is number[] overviewHeaders, context, - _fileKey: path.relative(docsDir, path.join(workDir, metaItem)), - }; + _fileKey: getHmrFileKey(realPath, docsDir), + } as SidebarItem; } const { @@ -143,12 +156,13 @@ export async function scanSideMeta( text: title, link: addRoutePrefix(pureLink), tag, + // FIXME: overviewHeaders is number[] overviewHeaders: info.overviewHeaders ? info.overviewHeaders : overviewHeaders, context: info.context ? info.context : context, - _fileKey: realPath ? path.relative(docsDir, realPath) : '', - }; + _fileKey: getHmrFileKey(realPath, docsDir), + } as SidebarItem; } if (type === 'dir') { @@ -160,32 +174,75 @@ export async function scanSideMeta( routePrefix, extensions, ); - const realPath = await detectFilePath(subDir, extensions); + + // Category index convention, display a document when clicking on the sidebar directory + // https://docusaurus.io/docs/sidebar/autogenerated#category-index-convention + + // 1. sameName /api, /api.md or /api.mdx, (this should be removed in Rspress 2.0) + let realPath = await detectFilePath(subDir, extensions); + let link: string; + let _fileKey: string; + + if (realPath) { + link = addRoutePrefix(pureLink); + _fileKey = getHmrFileKey(realPath, docsDir); + } else { + // 2. index /api, /api/index.md, /api/index.mdx + const indexFileRealPath = await detectFilePath( + join(subDir, 'index'), + extensions, + ); + link = indexFileRealPath ? addRoutePrefix(pureLink) : ''; + _fileKey = getHmrFileKey(indexFileRealPath, docsDir); + realPath = indexFileRealPath; + + // 3. if "index.mdx" or "index.md" or "index" is in _meta.json, index page should be placed to child sidebar + const isIndexFileInMetaItems = subSidebar.find(i => { + return ( + (i as { _fileKey: string | undefined })._fileKey === _fileKey + ); + }); + + if (isIndexFileInMetaItems) { + link = ''; + _fileKey = getHmrFileKey(indexFileRealPath, docsDir); + realPath = undefined; + } + } + + const { context: frontmatterContext = context } = realPath + ? await extractInfoFromFrontmatterWithRealPath(realPath, rootDir) + : {}; + return { text: label, collapsible, collapsed, items: subSidebar, - link: realPath ? addRoutePrefix(pureLink) : '', + link, tag, + // FIXME: overviewHeaders is number[] overviewHeaders, - context, - _fileKey: realPath ? path.relative(docsDir, realPath) : '', - }; + context: frontmatterContext, + _fileKey, + } as SidebarGroup; } if (type === 'divider') { - return { dividerType: dashed ? 'dashed' : 'solid' }; + return { + dividerType: dashed ? 'dashed' : 'solid', + } satisfies SidebarDivider; } if (type === 'section-header') { - return { sectionHeaderText: label, tag }; + return { sectionHeaderText: label, tag } satisfies SidebarSectionHeader; } return { text: label, - link: isExternalUrl(link) ? link : withBase(link, routePrefix), + link: link && isExternalUrl(link) ? link : withBase(link, routePrefix), tag, - } as SidebarItem; + context, + } satisfies SidebarItem; }), ); diff --git a/packages/runtime/src/utils.ts b/packages/runtime/src/utils.ts index a4e2a9f7c..1fe86abda 100644 --- a/packages/runtime/src/utils.ts +++ b/packages/runtime/src/utils.ts @@ -43,11 +43,7 @@ export function normalizeImagePath(imagePath: string) { if (!isProd) { return imagePath; } - if ( - isExternalUrl(imagePath) || - isDataUrl(imagePath) || - imagePath.startsWith('//') - ) { + if (isAbsoluteUrl(imagePath)) { return imagePath; } // only append base to internal non-relative urls @@ -58,4 +54,8 @@ export function normalizeImagePath(imagePath: string) { return withBase(imagePath); } +export function isAbsoluteUrl(path: string) { + return isExternalUrl(path) || isDataUrl(path) || path.startsWith('//'); +} + export { addLeadingSlash, removeTrailingSlash, normalizeSlash, isProduction }; diff --git a/packages/theme-default/src/components/Sidebar/SidebarGroup.tsx b/packages/theme-default/src/components/Sidebar/SidebarGroup.tsx index 4a848f91e..622a7c239 100644 --- a/packages/theme-default/src/components/Sidebar/SidebarGroup.tsx +++ b/packages/theme-default/src/components/Sidebar/SidebarGroup.tsx @@ -1,6 +1,6 @@ import type React from 'react'; import { useEffect, useRef } from 'react'; -import { type NormalizedSidebarGroup, SidebarItem } from '@rspress/shared'; +import type { NormalizedSidebarGroup } from '@rspress/shared'; import { useNavigate, normalizeHrefInRuntime as normalizeHref, @@ -11,7 +11,11 @@ import { Tag } from '@theme'; import styles from './index.module.scss'; import { SidebarItem as SidebarItemComp } from './SidebarItem'; import { SidebarDivider } from './SidebarDivider'; -import { highlightTitleStyle, type SidebarItemProps } from '.'; +import { + highlightTitleStyle, + isSidebarDivider, + type SidebarItemProps, +} from '.'; import { SvgWrapper } from '../SvgWrapper'; import { renderInlineMarkdown } from '../../logic'; @@ -169,7 +173,7 @@ export function SidebarGroup(props: SidebarItemProps) { }} > {(item as NormalizedSidebarGroup)?.items?.map((item, index) => - 'dividerType' in item ? ( + isSidebarDivider(item) ? ( { + return 'link' in item && isExternalUrl(item.link); +}; + export interface SidebarItemProps { id: string; item: ISidebarItem | NormalizedSidebarGroup; @@ -189,6 +200,27 @@ export function Sidebar(props: Props) { ); } + if (isSideBarCustomLink(item)) { + return ( +
+ +
+ ); + } + return ( Date: Wed, 13 Nov 2024 17:34:58 +0800 Subject: [PATCH 5/8] docs: update --- packages/document/docs/en/guide/basic/auto-nav-sidebar.mdx | 3 ++- packages/document/docs/zh/guide/basic/auto-nav-sidebar.mdx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/document/docs/en/guide/basic/auto-nav-sidebar.mdx b/packages/document/docs/en/guide/basic/auto-nav-sidebar.mdx index 43071bcb4..59a4b5999 100644 --- a/packages/document/docs/en/guide/basic/auto-nav-sidebar.mdx +++ b/packages/document/docs/en/guide/basic/auto-nav-sidebar.mdx @@ -233,8 +233,9 @@ In the case of describing **custom link**, the types are as follows: ```ts { type: 'custom-link'; - link: string; label: string; + link: string; + context?: string; } ``` diff --git a/packages/document/docs/zh/guide/basic/auto-nav-sidebar.mdx b/packages/document/docs/zh/guide/basic/auto-nav-sidebar.mdx index 825ed5175..59275250a 100644 --- a/packages/document/docs/zh/guide/basic/auto-nav-sidebar.mdx +++ b/packages/document/docs/zh/guide/basic/auto-nav-sidebar.mdx @@ -97,7 +97,7 @@ export type SideMetaItem = type: 'custom-link'; label: string; link: string; - context: string; + context?: string; }; ``` @@ -235,6 +235,7 @@ docs type: 'custom-link'; label: string; link: string; + context?: string; } ``` From 2448e5f7342170a606a6f1fe8d91a894f731f350 Mon Sep 17 00:00:00 2001 From: SoonIter Date: Wed, 13 Nov 2024 17:36:18 +0800 Subject: [PATCH 6/8] docs: update --- .changeset/two-lizards-rule.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/two-lizards-rule.md diff --git a/.changeset/two-lizards-rule.md b/.changeset/two-lizards-rule.md new file mode 100644 index 000000000..3fdb033c6 --- /dev/null +++ b/.changeset/two-lizards-rule.md @@ -0,0 +1,6 @@ +--- +'@rspress/plugin-auto-nav-sidebar': patch +'@rspress/theme-default': patch +--- + +support index convention and custom-link context From c66d41fc6adbec19b1755a8741deb6dded7babd5 Mon Sep 17 00:00:00 2001 From: SoonIter Date: Wed, 13 Nov 2024 18:03:38 +0800 Subject: [PATCH 7/8] =?UTF-8?q?chore:=20=E5=A6=82=E6=97=A0=E5=BF=85?= =?UTF-8?q?=E8=A6=81,=E5=8B=BF=E5=A2=9E=E5=AE=9E=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e/fixtures/auto-nav-sidebar/doc/guide/_meta.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/e2e/fixtures/auto-nav-sidebar/doc/guide/_meta.json b/e2e/fixtures/auto-nav-sidebar/doc/guide/_meta.json index 1f9d22260..9aa97c7e5 100644 --- a/e2e/fixtures/auto-nav-sidebar/doc/guide/_meta.json +++ b/e2e/fixtures/auto-nav-sidebar/doc/guide/_meta.json @@ -3,7 +3,6 @@ { "type": "dir", "name": "advanced", - "label": "Advanced", - "context": "advanced-dir" + "label": "Advanced" } ] From 1418e6b0125a291171471b10d016f29a91e6c616 Mon Sep 17 00:00:00 2001 From: Timeless0911 <50201324+Timeless0911@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:43:08 +0800 Subject: [PATCH 8/8] Update .changeset/two-lizards-rule.md --- .changeset/two-lizards-rule.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/two-lizards-rule.md b/.changeset/two-lizards-rule.md index 3fdb033c6..f7d52a6dd 100644 --- a/.changeset/two-lizards-rule.md +++ b/.changeset/two-lizards-rule.md @@ -1,6 +1,6 @@ --- '@rspress/plugin-auto-nav-sidebar': patch -'@rspress/theme-default': patch +'@rspress/theme-default': minor --- support index convention and custom-link context