Skip to content

Commit e50a9f9

Browse files
Copilotna-trium-144
andcommitted
Replace pagesList.ts with reading from public/docs/{lang}/index.yml
Co-authored-by: na-trium-144 <100704180+na-trium-144@users.noreply.github.com>
1 parent cf428cd commit e50a9f9

File tree

8 files changed

+104
-156
lines changed

8 files changed

+104
-156
lines changed

app/[docs_id]/page.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { splitMarkdown } from "./splitMarkdown";
77
import { PageContent } from "./pageContent";
88
import { ChatHistoryProvider } from "./chatHistory";
99
import { getChatFromCache, initContext } from "@/lib/chatHistory";
10-
import { getLanguageName, pagesList } from "@/pagesList";
10+
import { getPagesList } from "@/lib/getPagesList";
1111
import { isCloudflare } from "@/lib/detectCloudflare";
1212

1313
async function getMarkdownContent(docs_id: string): Promise<string> {
@@ -47,10 +47,13 @@ export async function generateMetadata({
4747

4848
const description = splitMdContent[0].content;
4949

50+
const lang_id = docs_id.split("-")[0];
5051
const chapter = docs_id.split("-")[1];
52+
const pagesList = await getPagesList();
53+
const langName = pagesList.find((l) => l.id === lang_id)?.name ?? lang_id;
5154

5255
return {
53-
title: `${getLanguageName(docs_id)}-${chapter}. ${title}`,
56+
title: `${langName}-${chapter}. ${title}`,
5457
description,
5558
};
5659
}
@@ -61,11 +64,13 @@ export default async function Page({
6164
params: Promise<{ docs_id: string }>;
6265
}) {
6366
const { docs_id } = await params;
64-
67+
const lang_id = docs_id.split("-")[0];
68+
const page_num = parseInt(docs_id.split("-")[1]);
69+
const pagesList = await getPagesList();
6570
if (
6671
!pagesList
67-
.find((lang) => docs_id.startsWith(`${lang.id}-`))
68-
?.pages.find((page) => docs_id.endsWith(`-${page.id}`))
72+
.find((lang) => lang.id === lang_id)
73+
?.pages.find((_, idx) => idx + 1 === page_num)
6974
) {
7075
notFound();
7176
}

app/[lang]/[pageId]/page.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { MarkdownSection } from "../[docs_id]/splitMarkdown";
88
import { PageContent } from "../[docs_id]/pageContent";
99
import { ChatHistoryProvider } from "../[docs_id]/chatHistory";
1010
import { getChatFromCache, initContext } from "@/lib/chatHistory";
11-
import { pagesList } from "@/pagesList";
11+
import { getPagesList } from "@/lib/getPagesList";
1212
import { isCloudflare } from "@/lib/detectCloudflare";
1313

1414
async function readDocFile(
@@ -111,14 +111,14 @@ export async function generateMetadata({
111111
params: Promise<{ lang: string; pageId: string }>;
112112
}): Promise<Metadata> {
113113
const { lang, pageId } = await params;
114+
const pagesList = await getPagesList();
114115
const langEntry = pagesList.find((l) => l.id === lang);
115-
const pageEntry = langEntry?.pages.find((p) => p.slug === pageId);
116+
const pageIndex = langEntry?.pages.findIndex((p) => p.slug === pageId) ?? -1;
117+
const pageEntry = pageIndex >= 0 ? langEntry?.pages[pageIndex] : undefined;
116118
if (!langEntry || !pageEntry) notFound();
117119

118-
const pageIndex = langEntry!.pages.findIndex((p) => p.slug === pageId);
119-
// pageIndex will be >= 0 since pageEntry was found via the same pages array
120120
return {
121-
title: `${langEntry!.lang}-${pageIndex + 1}. ${pageEntry!.title}`,
121+
title: `${langEntry!.name}-${pageIndex + 1}. ${pageEntry!.name}`,
122122
};
123123
}
124124

@@ -128,13 +128,13 @@ export default async function Page({
128128
params: Promise<{ lang: string; pageId: string }>;
129129
}) {
130130
const { lang, pageId } = await params;
131-
131+
const pagesList = await getPagesList();
132132
const langEntry = pagesList.find((l) => l.id === lang);
133133
const pageEntry = langEntry?.pages.find((p) => p.slug === pageId);
134134
if (!langEntry || !pageEntry) notFound();
135135

136136
const docsId = `${lang}/${pageId}`;
137-
const sections = await getMarkdownSections(lang, pageId, pageEntry!.title);
137+
const sections = await getMarkdownSections(lang, pageId, pageEntry!.name);
138138

139139
// AI用のドキュメント全文(見出し付きで結合)
140140
const documentContent = sections

app/layout.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { EmbedContextProvider } from "./terminal/embedContext";
1212
import { AutoAnonymousLogin } from "./accountMenu";
1313
import { SidebarMdProvider } from "./sidebar";
1414
import { RuntimeProvider } from "./terminal/runtime";
15+
import { getPagesList } from "@/lib/getPagesList";
1516

1617
export const metadata: Metadata = {
1718
title: {
@@ -20,9 +21,10 @@ export const metadata: Metadata = {
2021
},
2122
};
2223

23-
export default function RootLayout({
24+
export default async function RootLayout({
2425
children,
2526
}: Readonly<{ children: ReactNode }>) {
27+
const pagesList = await getPagesList();
2628
return (
2729
<html lang="ja">
2830
<body className="w-screen min-h-screen bg-transparent! text-inherit! m-0!">
@@ -36,7 +38,7 @@ export default function RootLayout({
3638
className="drawer-toggle"
3739
/>
3840
<div className="drawer-content flex flex-col">
39-
<Navbar />
41+
<Navbar pagesList={pagesList} />
4042
<EmbedContextProvider>
4143
<RuntimeProvider>{children}</RuntimeProvider>
4244
</EmbedContextProvider>
@@ -47,7 +49,7 @@ export default function RootLayout({
4749
aria-label="close sidebar"
4850
className="drawer-overlay"
4951
/>
50-
<Sidebar />
52+
<Sidebar pagesList={pagesList} />
5153
</div>
5254
</div>
5355
</SidebarMdProvider>

app/lib/getPagesList.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { getCloudflareContext } from "@opennextjs/cloudflare";
2+
import { readFile } from "node:fs/promises";
3+
import { join } from "node:path";
4+
import yaml from "js-yaml";
5+
import { isCloudflare } from "./detectCloudflare";
6+
7+
export interface PageEntry {
8+
slug: string;
9+
name: string;
10+
title: string;
11+
}
12+
13+
export interface LanguageEntry {
14+
id: string;
15+
name: string;
16+
description: string;
17+
pages: PageEntry[];
18+
}
19+
20+
interface IndexYml {
21+
name: string;
22+
description: string;
23+
pages: PageEntry[];
24+
}
25+
26+
const LANGUAGE_IDS = [
27+
"python",
28+
"ruby",
29+
"javascript",
30+
"typescript",
31+
"cpp",
32+
"rust",
33+
] as const;
34+
35+
async function readIndexYml(langId: string): Promise<string> {
36+
if (isCloudflare()) {
37+
const cfAssets = getCloudflareContext().env.ASSETS;
38+
const res = await cfAssets!.fetch(
39+
`https://assets.local/docs/${langId}/index.yml`
40+
);
41+
if (!res.ok) throw new Error(`Failed to fetch index.yml for ${langId}`);
42+
return await res.text();
43+
} else {
44+
return await readFile(
45+
join(process.cwd(), "public", "docs", langId, "index.yml"),
46+
"utf-8"
47+
);
48+
}
49+
}
50+
51+
export async function getPagesList(): Promise<LanguageEntry[]> {
52+
return await Promise.all(
53+
LANGUAGE_IDS.map(async (langId) => {
54+
const raw = await readIndexYml(langId);
55+
const data = yaml.load(raw) as IndexYml;
56+
return {
57+
id: langId,
58+
name: data.name,
59+
description: data.description,
60+
pages: data.pages,
61+
};
62+
})
63+
);
64+
}

app/navbar.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import Link from "next/link";
44
import { AccountMenu } from "./accountMenu";
55
import { ThemeToggle } from "./[docs_id]/themeToggle";
66
import { usePathname } from "next/navigation";
7-
import { pagesList } from "./pagesList";
7+
import { LanguageEntry } from "@/lib/getPagesList";
88

9-
function PageTitle() {
9+
function PageTitle({ pagesList }: { pagesList: LanguageEntry[] }) {
1010
const pathname = usePathname();
1111

1212
if(pathname === "/"){
@@ -19,15 +19,15 @@ function PageTitle() {
1919
const currentPage = pageIndex >= 0 ? currentGroup?.pages[pageIndex] : undefined;
2020
if(currentPage){
2121
return <>
22-
<span className="text-base mr-2">{currentGroup?.lang}-{pageIndex + 1}.</span>
23-
<span>{currentPage.title}</span>
22+
<span className="text-base mr-2">{currentGroup?.name}-{pageIndex + 1}.</span>
23+
<span>{currentPage.name}</span>
2424
</>
2525
}
2626

2727
console.warn(`navbar page name is not defined for pathname ${pathname}`);
2828
return null;
2929
}
30-
export function Navbar() {
30+
export function Navbar({ pagesList }: { pagesList: LanguageEntry[] }) {
3131

3232
return (
3333
<>
@@ -67,7 +67,7 @@ export function Navbar() {
6767
<span className="font-bold text-xl font-mono">my.code();</span>
6868
</Link>
6969
<div className="flex-1 hidden md:inline text-nowrap overflow-hidden text-ellipsis font-bold text-xl">
70-
<PageTitle />
70+
<PageTitle pagesList={pagesList} />
7171
</div>
7272
<div className="flex-1 md:hidden" />
7373
<ThemeToggle />

app/page.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Metadata } from "next";
22
import Link from "next/link";
3-
import { pagesList } from "./pagesList";
3+
import { getPagesList } from "@/lib/getPagesList";
44
import clsx from "clsx";
55

66
export const metadata: Metadata = {
@@ -9,7 +9,8 @@ export const metadata: Metadata = {
99
"環境構築不要、その場で実践。AIアシスタントとの対話履歴があなただけの教材へと進化する、新しいプログラミング学習サイトです。",
1010
};
1111

12-
export default function Home() {
12+
export default async function Home() {
13+
const pagesList = await getPagesList();
1314
return (
1415
<div className="p-4">
1516
<div className="hero bg-gradient-to-br from-primary/30 via-secondary/15 to-accent/30 rounded-lg my-6 py-8 sm:px-4">
@@ -41,14 +42,14 @@ export default function Home() {
4142
return (
4243
<Link
4344
key={group.id}
44-
href={`${group.id}-${group.pages[0].id}`}
45+
href={`${group.id}/${group.pages[0].slug}`}
4546
className={clsx(
4647
"card card-border card-md bg-base-200 shadow-lg",
4748
"hover:shadow-xl transition-all hover:-translate-y-1",
4849
)}
4950
>
5051
<div className="card-body">
51-
<h2 className="card-title">{group.lang}</h2>
52+
<h2 className="card-title">{group.name}</h2>
5253
<p>{group.description}</p>
5354
<div className="justify-end card-actions">
5455
<div className="btn btn-primary">はじめる</div>

app/pagesList.ts

Lines changed: 0 additions & 124 deletions
This file was deleted.

0 commit comments

Comments
 (0)