diff options
| author | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-09-21 08:25:26 +0900 |
|---|---|---|
| committer | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-09-21 08:25:26 +0900 |
| commit | b3ad7c9e7d516082733930ef86b550dcdd8c66e2 (patch) | |
| tree | 39776523d81ef9d95295e9487403ff570408b03f /src/plugins | |
| parent | f11d15bdf9839db30a9c61fc8f7ce39279ed673c (diff) | |
ホーム: git履歴から生成する更新情報を追加し、サイドバーの実績を集約
Diffstat (limited to 'src/plugins')
| -rw-r--r-- | src/plugins/updates.ts | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/src/plugins/updates.ts b/src/plugins/updates.ts new file mode 100644 index 0000000..cd6dd54 --- /dev/null +++ b/src/plugins/updates.ts @@ -0,0 +1,76 @@ +import { execSync } from "node:child_process"; +import { readFileSync, writeFileSync, mkdirSync } from "node:fs"; + +/** + * ホームページの「更新情報」をビルド時に生成する。 + * + * git の履歴から「新しく公開したページ」だけを拾い(--diff-filter=A)、 + * そのページのフロントマターの title と URL を組みにして src/data/updates.json に書き出す。 + * 加筆や内部の修正は拾わないので、一覧が作業ログで埋まらない。 + * + * 生成結果はコミットしておく(git の履歴がない環境でもビルドできるように)。 + */ +export default function updatesIntegration() { + return { + name: "build-updates", + hooks: { + "astro:config:setup": () => { + const items: { date: string; title: string; url: string; group: string }[] = []; + try { + const out = execSync( + 'git log --diff-filter=A --name-only --date=short --format="%x01%ad" -- src/content/docs', + { encoding: "utf-8", maxBuffer: 64 * 1024 * 1024 }, + ); + // 新しく追加されたファイル → そのコミットの日付(git log は新しい順なので最初の出現が追加時) + const added = new Map<string, string>(); + let date = ""; + for (const line of out.split("\n")) { + if (line.startsWith("\u0001")) { + date = line.slice(1).trim(); + continue; + } + const file = line.trim(); + if (!file.endsWith(".mdx") || file.endsWith("/index.mdx")) continue; + if (!added.has(file)) added.set(file, date); + } + + const reiwa = (dir: string) => { + const n = Number(dir.replace(/^r(\d+)d$/, "$1")); + return n === 1 ? "令和元年" : `令和${n}年`; + }; + + for (const [file, d] of added) { + try { + const src = readFileSync(file, "utf-8"); + const m = src.match(/^title:\s*"?(.+?)"?\s*$/m); + if (!m) continue; + const slug = file + .replace(/^src\/content\/docs\//, "") + .replace(/\.mdx$/, ""); + const url = `/${slug}/`; + let group = ""; + const mm = slug.match(/^ippan-situmon\/(r\d+d)\/(\d+)gatu\//); + if (mm) group = `${reiwa(mm[1])}${mm[2]}月定例会`; + items.push({ date: d, title: m[1], url, group }); + } catch { + // 追加後に改名・削除されたファイルは飛ばす + } + } + items.sort((a, b) => b.date.localeCompare(a.date)); + } catch (e) { + console.warn("[updates] git から取得できませんでした:", (e as Error).message); + } + try { + mkdirSync("src/data", { recursive: true }); + writeFileSync( + "src/data/updates.json", + JSON.stringify(items.slice(0, 40), null, 2) + "\n", + ); + console.log(`[updates] ${items.length}件のうち直近${Math.min(items.length, 40)}件を書き出しました`); + } catch (e) { + console.warn("[updates] 書き出しに失敗しました:", (e as Error).message); + } + }, + }, + }; +} |
