Skip to content

Commit 92d159d

Browse files
committed
feat: add x-next-router-type cookie
1 parent ef98892 commit 92d159d

File tree

6 files changed

+100
-36
lines changed

6 files changed

+100
-36
lines changed

apps/docs/src/app/[locale]/docs/[[...slug]]/page.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { DocsLayout } from '@/components/layout';
2+
import { type RouterType, routerTypeCookie } from '@/lib/const';
23
import { getPage } from '@/lib/page';
34
import { getDocsLayoutTree, getPageTreePeers } from '@/lib/pageTree';
45
import { type Page, type Source, sourceMap } from '@/lib/source';
@@ -10,11 +11,14 @@ import { Card, Cards } from 'fumadocs-ui/components/card';
1011
import { createRelativeLink } from 'fumadocs-ui/mdx';
1112
import { DocsBody, DocsPage, DocsTitle } from 'fumadocs-ui/page';
1213
import { type Locale, useLocale } from 'next-intl';
14+
import { cookies } from 'next/headers';
1315
import { notFound } from 'next/navigation';
1416

1517
export default async function Docs(props: {
1618
params: Promise<{ locale: Locale; slug?: string[] }>;
1719
}) {
20+
const routerType = (await cookies()).get(routerTypeCookie)
21+
?.value as RouterType;
1822
const params = await props.params;
1923
const slug = params.slug || [];
2024
const locale = params.locale;
@@ -44,8 +48,9 @@ export default async function Docs(props: {
4448

4549
return (
4650
<DocsLayout
51+
routerType={routerType}
4752
docId={docId}
48-
pageTree={getDocsLayoutTree(source.pageTree, slug)}
53+
pageTree={getDocsLayoutTree(source.pageTree, docId, routerType)}
4954
>
5055
<DocsPage
5156
toc={toc}

apps/docs/src/components/layout.tsx

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use client';
22

33
import { useBaseOptions } from '@/hooks/useLayoutOptions';
4+
import type { RouterType } from '@/lib/const';
45
import { parseDocId } from '@/lib/utils';
56
import {
67
NextAppIcon,
@@ -20,13 +21,32 @@ export function DocsLayout({
2021
children,
2122
pageTree,
2223
docId,
24+
routerType,
2325
}: {
2426
children: ReactNode;
2527
pageTree: PageTree.Root;
2628
docId: string;
29+
routerType: RouterType;
2730
}) {
2831
const baseOptions = useBaseOptions();
29-
const { appDocsRoot, pagesDocsRoot, docsRoot } = parseDocId(docId);
32+
const { appDocsRoot, pagesDocsRoot, docsRoot, docUrl, isPages } =
33+
parseDocId(docId);
34+
const options = [
35+
{
36+
title: 'Using App Router',
37+
description: 'Features available in /app',
38+
icon: <NextAppIcon />,
39+
url: appDocsRoot,
40+
...(routerType !== 'pages' ? { urls: new Set([docUrl]) } : {}),
41+
},
42+
{
43+
title: 'Using Pages Router',
44+
description: 'Features available in /pages',
45+
icon: <NextPagesIcon />,
46+
url: pagesDocsRoot,
47+
...(routerType === 'pages' ? { urls: new Set([docUrl]) } : {}),
48+
},
49+
];
3050

3151
const docsLayout: DocsLayoutProps = {
3252
...baseOptions,
@@ -35,23 +55,7 @@ export function DocsLayout({
3555
sidebar: {
3656
banner: (
3757
<>
38-
<RootToggle
39-
options={[
40-
{
41-
title: 'Using App Router',
42-
description: 'Features available in /app',
43-
icon: <NextAppIcon />,
44-
url: appDocsRoot,
45-
urls: new Set([docsRoot, appDocsRoot]),
46-
},
47-
{
48-
title: 'Using Pages Router',
49-
description: 'Features available in /pages',
50-
icon: <NextPagesIcon />,
51-
url: pagesDocsRoot,
52-
},
53-
]}
54-
/>
58+
<RootToggle options={options} />
5559
<RootToggle
5660
options={[
5761
{

apps/docs/src/lib/const.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export type RouterType = 'app' | 'pages' | undefined;
2+
export const routerTypeCookie = 'x-next-router-type';

apps/docs/src/lib/pageTree.ts

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import type { PageTree } from 'fumadocs-core/server';
2+
import type { RouterType } from './const';
3+
import { parseDocId } from './utils';
24

35
/**
46
* Get other page tree nodes that lives under the same parent
@@ -49,25 +51,34 @@ export function cloneRoot(tree: PageTree.Root) {
4951
};
5052
}
5153

52-
export function getDocsLayoutTree(tree: PageTree.Root, slug: string[]) {
53-
const isV14 = slug[0] === '14';
54-
const isV13 = slug[0] === '13';
55-
const isLatest = !isV14 && !isV13;
54+
export function getDocsLayoutTree(
55+
tree: PageTree.Root,
56+
docId: string,
57+
routerType: RouterType,
58+
) {
59+
const { isV13, isV14, isVLatest, isPages, version } = parseDocId(docId);
5660

5761
const root = cloneRoot(tree);
5862
for (const node of tree.children) {
59-
if (isLatest) {
60-
const isPages = slug[0] === 'pages';
63+
if (isVLatest) {
6164
// App
62-
if (!isPages && node.$id === '01-app' && node.type === 'folder') {
65+
if (
66+
routerType !== 'pages' &&
67+
node.$id === '01-app' &&
68+
node.type === 'folder'
69+
) {
6370
const children = node.children;
6471
if (children[0].type === 'folder') {
6572
children[0].defaultOpen = true;
6673
}
6774
root.children.push(...children);
6875
}
6976
// Pages
70-
if (isPages && node.$id === '02-pages' && node.type === 'folder') {
77+
if (
78+
routerType === 'pages' &&
79+
node.$id === '02-pages' &&
80+
node.type === 'folder'
81+
) {
7182
const children = node.children;
7283
if (children[0].type === 'folder') {
7384
children[0].defaultOpen = true;
@@ -86,14 +97,12 @@ export function getDocsLayoutTree(tree: PageTree.Root, slug: string[]) {
8697
}
8798

8899
if (isV13 || isV14) {
89-
const version = isV14 ? '14' : '13';
90100
const gettingStarted = `${version}/01-getting-started`;
91101
const appFolder = `${version}/02-app`;
92102
const pagesFolder = `${version}/03-pages`;
93103
if (node.$id === version && node.type === 'folder') {
94104
const children = node.children;
95105

96-
const isPages = slug[1] === 'pages';
97106
for (const child of children) {
98107
const expandChildren = [appFolder, pagesFolder];
99108
if (
@@ -105,10 +114,18 @@ export function getDocsLayoutTree(tree: PageTree.Root, slug: string[]) {
105114
if (item.type === 'folder') item.defaultOpen = true;
106115
}
107116
}
108-
if (!isPages && child.$id === appFolder && child.type === 'folder') {
117+
if (
118+
routerType !== 'pages' &&
119+
child.$id === appFolder &&
120+
child.type === 'folder'
121+
) {
109122
root.children.push(...child.children);
110123
}
111-
if (isPages && child.$id === pagesFolder && child.type === 'folder') {
124+
if (
125+
routerType === 'pages' &&
126+
child.$id === pagesFolder &&
127+
child.type === 'folder'
128+
) {
112129
root.children.push(...child.children);
113130
}
114131

apps/docs/src/lib/utils.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ export const getDocTags = (id: string) => {
5555
* @returns
5656
*/
5757
export const getDocId = (locale: Locale, docUrl: string) => {
58-
return `${locale}${docUrl}`;
58+
const id = `${locale}${docUrl}`;
59+
if (id.endsWith('/')) {
60+
return id.slice(0, -1);
61+
}
62+
return id;
5963
};
6064

6165
/**
@@ -67,6 +71,9 @@ export const getDocId = (locale: Locale, docUrl: string) => {
6771
*/
6872
export const parseDocId = (id: string) => {
6973
const paths = id.split('/');
74+
if (paths[paths.length - 1] === '') {
75+
paths.pop();
76+
}
7077
const locale = paths[0];
7178
// const tags = paths.slice(0, 2);
7279
const slugs = paths.slice(2);
@@ -95,16 +102,18 @@ export const parseDocId = (id: string) => {
95102
const whereTag = !isVLatest ? `${locale}/docs/${version}` : `${locale}/docs`;
96103

97104
return {
105+
slugs,
98106
locale: paths[0],
99107
version,
100108
isApp,
101109
isPages,
102110
isV13,
103111
isV14,
104112
isVLatest,
105-
docsRoot: isVLatest ? '/docs' : `/docs/${slugs[0]}`,
106-
appDocsRoot: isVLatest ? '/docs/app' : `/docs/${slugs[0]}/app`,
107-
pagesDocsRoot: isVLatest ? '/docs/pages' : `/docs/${slugs[0]}/pages`,
113+
docUrl: `/${paths.slice(1).join('/')}`,
114+
docsRoot: isVLatest ? '/docs' : `/docs/${version}`,
115+
appDocsRoot: isVLatest ? '/docs/app' : `/docs/${version}/app`,
116+
pagesDocsRoot: isVLatest ? '/docs/pages' : `/docs/${version}/pages`,
108117
docTag,
109118
appTag,
110119
pagesTag,

apps/docs/src/middleware.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,34 @@
11
import createMiddleware from 'next-intl/middleware';
2+
import type { NextRequest } from 'next/server';
23
import { routing } from './i18n/routing';
4+
import { routerTypeCookie } from './lib/const';
5+
import { parseDocId } from './lib/utils';
36

4-
export default createMiddleware(routing);
7+
export default async function middleware(request: NextRequest) {
8+
const url = new URL(request.url);
9+
const isDocs = url.pathname.startsWith('/docs');
10+
if (isDocs) {
11+
const docId = `en${url.pathname}`;
12+
const { isPages, isApp } = parseDocId(docId);
13+
if (isPages || isApp) {
14+
// Set the cookie so we could get this in the server
15+
request.cookies.set(routerTypeCookie, isPages ? 'pages' : 'app');
16+
}
17+
}
18+
19+
const handleI18nRouting = createMiddleware(routing);
20+
const response = handleI18nRouting(request);
21+
22+
if (isDocs) {
23+
const docId = `en${url.pathname}`;
24+
const { isPages, isApp } = parseDocId(docId);
25+
if (isPages || isApp) {
26+
response.cookies.set(routerTypeCookie, isPages ? 'pages' : 'app');
27+
}
28+
}
29+
30+
return response;
31+
}
532

633
export const config = {
734
// Match all pathnames except for

0 commit comments

Comments
 (0)