diff --git a/app/lib/docs.ts b/app/lib/docs.ts index 2f16c47..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"); } @@ -167,15 +175,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 +211,31 @@ 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)` ); } }