Skip to content

Commit f2e1867

Browse files
authored
Merge pull request #166 from ut-code/copilot/create-language-directories
Restructure public/docs/ into per-language directory hierarchy with app route migration
2 parents c22b5d2 + 9fa2c0a commit f2e1867

872 files changed

Lines changed: 21038 additions & 17457 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
/.open-next
44
/cloudflare-env.d.ts
55

6+
# generated docs section file lists (regenerated by npm run generateSections)
7+
/public/docs/**/sections.yml
8+
9+
# generated languages list (regenerated by npm run generateLanguages)
10+
/public/docs/languages.yml
11+
612
# dependencies
713
/node_modules
814
/.pnp

README.md

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,49 @@ npm run lint
5858
現在は本番環境(my-code.utcode.net)はCoolifyでデプロイしています。
5959
Cloudflare Worker のビルドログとステータス表示が見れますが、そちらは使っていません。
6060

61-
## ベースとなるドキュメントの作り方
61+
## ドキュメント
62+
63+
* ドキュメントはセクション(見出し)ごとにわけ、 public/docs/言語id/ページid/並び替え用連番-セクション名.md に置く。
64+
* ページはディレクトリの名前によらず 言語id/index.yml に書かれている順で表示される。
65+
* セクションはセクションIDによらずファイル名順で表示される。
66+
* 各セクションのfrontmatter (各ページ最初のセクション(-intro.md)を除く)
67+
```yml
68+
id: 一意なセクションID。ファイル名・ディレクトリ名と一致していなくても良い。バックエンドがこのセクションIDで識別するので、一度コミットしたら変更不可(ファイル名は何度変えても良い)
69+
title: セクションタイトルと同じものをmd記法を使わずに書いた文字列
70+
level: セクションの見出しレベル(2〜6が使用可)
71+
```
72+
* コード例はそれが配置されているセクションの内容と関連するようにする。
73+
````md
74+
## 制御構文
75+
### if
76+
if文の説明…
77+
### switch
78+
switch文の説明…
79+
80+
ifとswitch共通の注意事項... → ## 制御構文 に移す
81+
```
82+
ifとswitchを使ったコード例… → 2つのコード例に分割する
83+
(分割が難しい(かつ説明が短い)場合は、1つのセクションで全部説明してコード例を載せるのでもよい)
84+
```
85+
````
86+
* コード例や注意事項などを不必要に独立したセクションにするのは避ける
87+
````md
88+
## hoge
89+
hogeの説明…
90+
### hogeの使用場面 →この見出しいらない
91+
**hogeの使用場面** はok
92+
- 説明
93+
- 説明
94+
### hogeの使用例 →この見出しいらない
95+
```
96+
hogeを使ったコード例…
97+
```
98+
````
99+
* REPLのコード例は1セクションに最大1つまで。
100+
* コードエディターとコード実行ブロックはいくつでも置けます。
101+
* ページ0以外の各ページの最後はレベル2見出し「この章のまとめ」と、レベル3見出し「練習問題n」を置く
102+
103+
### ベースとなるドキュメントの作り方
62104

63105
- web版の ~~Gemini2.5Pro~~ Gemini3Pro を用いる。
64106
- 以下のプロンプトで章立てを考えさせる
@@ -107,7 +149,6 @@ Cloudflare Worker のビルドログとステータス表示が見れますが
107149
Hello
108150
```
109151
````
110-
- 練習問題の見出しは「この章のまとめ」の直下のレベル3見出しで、 `### 練習問題n` または `### 練習問題n: タイトル` とする
111152
- 練習問題のファイル名は不都合がなければ `practice(章番号)_(問題番号).拡張子` で統一。空でもよいのでファイルコードブロックとexecコードブロックを置く
112153
- 1章にはたぶん練習問題要らない。
113154

app/[docs_id]/page.tsx

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

app/[docs_id]/splitMarkdown.ts

Lines changed: 0 additions & 47 deletions
This file was deleted.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { useState, FormEvent, useEffect } from "react";
88
// } from "../actions/questionExample";
99
// import { getLanguageName } from "../pagesList";
1010
import { DynamicMarkdownSection } from "./pageContent";
11-
import { useEmbedContext } from "../terminal/embedContext";
11+
import { useEmbedContext } from "@/terminal/embedContext";
1212
import { useChatHistoryContext } from "./chatHistory";
1313
import { askAI } from "@/actions/chatActions";
1414

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import Markdown, { Components, ExtraProps } from "react-markdown";
22
import remarkGfm from "remark-gfm";
33
import removeComments from "remark-remove-comments";
44
import remarkCjkFriendly from "remark-cjk-friendly";
5-
import { EditorComponent, getAceLang } from "../terminal/editor";
6-
import { ExecFile } from "../terminal/exec";
5+
import { EditorComponent, getAceLang } from "@/terminal/editor";
6+
import { ExecFile } from "@/terminal/exec";
77
import { JSX, ReactNode } from "react";
88
import { getRuntimeLang } from "@/terminal/runtime";
99
import { ReplTerminal } from "@/terminal/repl";
@@ -64,6 +64,8 @@ export function Heading({
6464
children: ReactNode;
6565
}) {
6666
switch (level) {
67+
case 0:
68+
return null;
6769
case 1:
6870
return <h1 className="text-2xl font-bold my-4">{children}</h1>;
6971
case 2:

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

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { Metadata } from "next";
2+
import { notFound } from "next/navigation";
3+
import { PageContent } from "./pageContent";
4+
import { ChatHistoryProvider } from "./chatHistory";
5+
import { getChatFromCache, initContext } from "@/lib/chatHistory";
6+
import { getMarkdownSections, getPagesList } from "@/lib/docs";
7+
8+
export async function generateMetadata({
9+
params,
10+
}: {
11+
params: Promise<{ lang: string; pageId: string }>;
12+
}): Promise<Metadata> {
13+
const { lang, pageId } = await params;
14+
const pagesList = await getPagesList();
15+
const langEntry = pagesList.find((l) => l.id === lang);
16+
const pageEntry = langEntry?.pages.find((p) => p.slug === pageId);
17+
if (!langEntry || !pageEntry) notFound();
18+
19+
const sections = await getMarkdownSections(lang, pageId);
20+
const description = sections[0].rawContent;
21+
22+
return {
23+
title: `${langEntry!.name}-${pageEntry.index}. ${pageEntry.title}`,
24+
description,
25+
};
26+
}
27+
28+
export default async function Page({
29+
params,
30+
}: {
31+
params: Promise<{ lang: string; pageId: string }>;
32+
}) {
33+
const { lang, pageId } = await params;
34+
const pagesList = await getPagesList();
35+
const langEntry = pagesList.find((l) => l.id === lang);
36+
const pageEntry = langEntry?.pages.find((p) => p.slug === pageId);
37+
if (!langEntry || !pageEntry) notFound();
38+
39+
const docsId = `${lang}/${pageId}`;
40+
const sections = await getMarkdownSections(lang, pageId);
41+
42+
// AI用のドキュメント全文(rawContentを結合)
43+
const documentContent = sections.map((s) => s.rawContent).join("\n");
44+
45+
const context = await initContext();
46+
const initialChatHistories = await getChatFromCache(docsId, context);
47+
48+
return (
49+
<ChatHistoryProvider
50+
initialChatHistories={initialChatHistories}
51+
docs_id={docsId}
52+
>
53+
<PageContent
54+
documentContent={documentContent}
55+
splitMdContent={sections}
56+
pageEntry={pageEntry}
57+
docs_id={docsId}
58+
lang={lang}
59+
pageId={pageId}
60+
/>
61+
</ChatHistoryProvider>
62+
);
63+
}

0 commit comments

Comments
 (0)