Skip to content
Merged
23 changes: 23 additions & 0 deletions app/[docs_id]/splitMarkdownClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { MarkdownSection } from "./splitMarkdown";

export function splitMarkdownClient(content: string): MarkdownSection[] {
const lines = content.split("\n");
const sections: MarkdownSection[] = [];
let current: MarkdownSection | null = null;

for (const line of lines) {
const match = line.match(/^(#{1,6})\s+(.*)/); // 見出しを検出
if (match) {
if (current) sections.push(current); // 前のセクションを保存
current = {
level: match[1].length, // 見出しレベル(# の数)
title: match[2].trim(), // 見出しタイトル
content: "", // 内容は後続行で追加
};
} else if (current) {
current.content += line + "\n"; // セクション内容に追加
}
}
if (current) sections.push(current); // 最後のセクションを保存
return sections.map((s) => ({ ...s, content: s.content.trim() }));
}
75 changes: 48 additions & 27 deletions app/sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,63 @@
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import useSWR from 'swr'
import { splitMarkdownClient } from "./[docs_id]/splitMarkdownClient";



export function Sidebar() {
const fetcher = (url: string | URL | Request<unknown, CfProperties<unknown>>) => fetch(url).then((r) => r.text())
const pathname = usePathname();
const docs_id = pathname.replace(/^\//, "");
const { data, error, isLoading } = useSWR(
`/docs/${docs_id}.md`,
fetcher
)

if (isLoading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>

const pages = [
{ id: "python-1", title: "1. 環境構築と基本思想" },
{ id: "python-2", title: "2. 基本構文とデータ型" },
{ id: "python-3", title: "3. リスト、タプル、辞書、セット" },
{ id: "python-4", title: "4. 制御構文と関数" },
{ id: "python-5", title: "5. モジュールとパッケージ" },
{ id: "python-6", title: "6. オブジェクト指向プログラミング" },
{ id: "python-7", title: "7. ファイルの入出力とコンテキストマネージャ" },
{ id: "python-8", title: "8. 例外処理" },
{ id: "python-9", title: "9. ジェネレータとデコレータ" },
];


const splitmdcontent = splitMarkdownClient(data ?? "")
return (
<div className="bg-base-200 min-h-full w-80 p-4">
{/* todo: 背景色ほんとにこれでいい? */}
<h2 className="hidden lg:block text-xl font-bold mb-4">
{/* サイドバーが常時表示されている場合のみ */}
Navbar Title
</h2>

<ol className="menu w-full list-decimal list-outside">
<li>
<Link href="/python-1">1. 環境構築と基本思想</Link>
</li>
<li>
<Link href="/python-2">2. 基本構文とデータ型</Link>
</li>
<li>
<Link href="/python-3">3. リスト、タプル、辞書、セット</Link>
</li>
<li>
<Link href="/python-4">4. 制御構文と関数</Link>
</li>
<li>
<Link href="/python-5">5. モジュールとパッケージ</Link>
</li>
<li>
<Link href="/python-6">6. オブジェクト指向プログラミング</Link>
</li>
<li>
<Link href="/python-7">7. ファイルの入出力とコンテキストマネージャ</Link>
</li>
<li>
<Link href="/python-8">8. 例外処理</Link>
</li>
<li>
<Link href="/python-9">9. ジェネレータとデコレータ</Link>
</li>
{pages.map((page) => (
<li key={page.id}>
<Link href={`/${page.id}`}>{page.title}</Link>
{page.id === docs_id && (
<ul className="ml-4 mt-2 list-disc text-sm">
{splitmdcontent
.filter(section => section.level !== 1)
.map((section, idx) => (
<li key={idx}>{section.title}</li>
))}
</ul>
)}

</li>
))}
</ol>
</div>
);
}

23 changes: 23 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"react-markdown": "^10.1.0",
"react-syntax-highlighter": "^15.6.1",
"remark-gfm": "^4.0.1",
"swr": "^2.3.6",
"zod": "^4.0.17"
},
"devDependencies": {
Expand Down