From 7c87b28dded52b39167c499030cd42310646d2b5 Mon Sep 17 00:00:00 2001 From: na-trium-144 <100704180+na-trium-144@users.noreply.github.com> Date: Mon, 9 Mar 2026 20:32:22 +0900 Subject: [PATCH 1/2] =?UTF-8?q?sections.json=E3=81=AB=E3=82=BB=E3=82=AF?= =?UTF-8?q?=E3=82=B7=E3=83=A7=E3=83=B3=E3=81=AE=E5=90=8D=E5=89=8D=E3=81=A0?= =?UTF-8?q?=E3=81=91=E3=81=A7=E3=81=AA=E3=81=8F=E5=86=85=E5=AE=B9=E3=82=92?= =?UTF-8?q?=E5=85=A8=E9=83=A8=E5=85=A5=E3=82=8C=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/docs.ts | 73 +++++++++++++++++-------------------- scripts/generateDocsMeta.ts | 9 ++--- 2 files changed, 37 insertions(+), 45 deletions(-) diff --git a/app/lib/docs.ts b/app/lib/docs.ts index 2f16c47..d413e1e 100644 --- a/app/lib/docs.ts +++ b/app/lib/docs.ts @@ -167,15 +167,27 @@ export async function getPagesList(): Promise { ); } -export async function getSectionsList( +export async function getRevisions( + sectionId: SectionId +): Promise { + const revisionsYml = await readPublicFile(`docs/revisions.yml`); + return (yaml.load(revisionsYml) as Record)[ + sectionId + ]; +} + +/** + * public/docs/{lang}/{pageId}/ 以下のmdファイルを結合して MarkdownSection[] を返す。 + */ +export async function getMarkdownSections( lang: LangId, page: PageSlug -): Promise { +): Promise { if (isCloudflare()) { const sectionsJson = await readPublicFile( `docs/${lang}/${page}/sections.json` ); - return JSON.parse(sectionsJson) as string[]; + return JSON.parse(sectionsJson) as MarkdownSection[]; } else { function naturalSortMdFiles(a: string, b: string): number { // -intro.md always comes first @@ -191,48 +203,29 @@ export async function getSectionsList( } return a.localeCompare(b); } - return (await readdir(join(process.cwd(), "public", "docs", lang, page))) + const files = (await readdir(join(process.cwd(), "public", "docs", lang, page))) .filter((f) => f.endsWith(".md")) .sort(naturalSortMdFiles); - } -} -export async function getRevisions( - sectionId: SectionId -): Promise { - const revisionsYml = await readPublicFile(`docs/revisions.yml`); - return (yaml.load(revisionsYml) as Record)[ - sectionId - ]; -} - -/** - * public/docs/{lang}/{pageId}/ 以下のmdファイルを結合して MarkdownSection[] を返す。 - */ -export async function getMarkdownSections( - lang: LangId, - page: PageSlug -): Promise { - const files = await getSectionsList(lang, page); - - const sections: MarkdownSection[] = []; - for (const file of files) { - const raw = await readPublicFile(`docs/${lang}/${page}/${file}`); - if (file === "-intro.md") { - // イントロセクションはフロントマターなし・見出しなし - sections.push({ - file, - id: introSectionId({ lang, page }), - level: 1, - title: "", - rawContent: raw, - md5: crypto.createHash("md5").update(raw).digest("base64"), - }); - } else { - sections.push(parseFrontmatter(raw, file)); + const sections: MarkdownSection[] = []; + for (const file of files) { + const raw = await readPublicFile(`docs/${lang}/${page}/${file}`); + if (file === "-intro.md") { + // イントロセクションはフロントマターなし・見出しなし + sections.push({ + file, + id: introSectionId({ lang, page }), + level: 1, + title: "", + rawContent: raw, + md5: crypto.createHash("md5").update(raw).digest("base64"), + }); + } else { + sections.push(parseFrontmatter(raw, file)); + } } + return sections; } - return sections; } export function introSectionId(path: PagePath) { return `${path.lang}-${path.page}-intro` as SectionId; diff --git a/scripts/generateDocsMeta.ts b/scripts/generateDocsMeta.ts index 5650d51..aa7744c 100644 --- a/scripts/generateDocsMeta.ts +++ b/scripts/generateDocsMeta.ts @@ -3,7 +3,7 @@ import { writeFile } from "node:fs/promises"; import { join } from "node:path"; -import { getPagesList, getSectionsList } from "@/lib/docs"; +import { getMarkdownSections, getPagesList } from "@/lib/docs"; const docsDir = join(process.cwd(), "public", "docs"); @@ -17,15 +17,14 @@ console.log( for (const lang of langEntries) { for (const page of lang.pages) { - const files = await getSectionsList(lang.id, page.slug); - const filesJson = JSON.stringify(files); + const sections = await getMarkdownSections(lang.id, page.slug); await writeFile( join(docsDir, lang.id, page.slug, "sections.json"), - filesJson, + JSON.stringify(sections), "utf-8" ); console.log( - `Generated ${lang.id}/${page.slug}/sections.json (${files.length} files)` + `Generated ${lang.id}/${page.slug}/sections.json (${sections.length} files)` ); } } From fe9c78672f7197fc5b223c373b1f37e88ebd0f30 Mon Sep 17 00:00:00 2001 From: na-trium-144 <100704180+na-trium-144@users.noreply.github.com> Date: Mon, 9 Mar 2026 20:38:10 +0900 Subject: [PATCH 2/2] =?UTF-8?q?readPublicFile=E3=82=92=E3=82=AD=E3=83=A3?= =?UTF-8?q?=E3=83=83=E3=82=B7=E3=83=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/docs.ts | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/app/lib/docs.ts b/app/lib/docs.ts index d413e1e..4104a9b 100644 --- a/app/lib/docs.ts +++ b/app/lib/docs.ts @@ -112,18 +112,26 @@ export interface SectionRevision { path: string; } +const publicFileCache = new Map>(); async function readPublicFile(path: string): Promise { try { if (isCloudflare()) { - const cfAssets = getCloudflareContext().env.ASSETS; - const res = await cfAssets!.fetch(`https://assets.local/${path}`); - if (!res.ok) { - console.error( - `Failed to fetch ${path}: ${res.status} ${await res.text()}` - ); - notFound(); + if (publicFileCache.has(path)) { + return publicFileCache.get(path)!; } - return await res.text(); + const p = (async () => { + const cfAssets = getCloudflareContext().env.ASSETS; + const res = await cfAssets!.fetch(`https://assets.local/${path}`); + if (!res.ok) { + console.error( + `Failed to fetch ${path}: ${res.status} ${await res.text()}` + ); + notFound(); + } + return await res.text(); + })(); + publicFileCache.set(path, p); + return p; } else { return await readFile(join(process.cwd(), "public", path), "utf-8"); } @@ -203,7 +211,9 @@ export async function getMarkdownSections( } return a.localeCompare(b); } - const files = (await readdir(join(process.cwd(), "public", "docs", lang, page))) + const files = ( + await readdir(join(process.cwd(), "public", "docs", lang, page)) + ) .filter((f) => f.endsWith(".md")) .sort(naturalSortMdFiles);