2025/07/22 23:32
会社の最終出社も終わってかなり暇になったので、ずっと手をつけていなかったブログの改修をすることにした。
さてコード改修するかと思ってローカルサーバーを立ち上げると何かAPI keyの問題でinternal errorが出てしまい、色々面倒になったので思い切ってmarkdownファイルでのコンテンツ管理に切り替える。
プロジェクト内に配置したファイルを読み込んで展開するように修正する。
記事一覧画面では.mdで終わるものをid毎に取得してソートして貰うようにclaude codeに書いて貰った。
export async function getAllArticles(): Promise<Article[]> { const fileNames = fs.readdirSync(articlesDirectory); const articles = await Promise.all( fileNames .filter((name) => name.endsWith(".md")) .map(async (name) => { const id = name.replace(/\.md$/, ""); return await getArticleById(id); }), ); return articles.sort((a, b) => { return ( new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime() ); }); }
一覧・詳細画面のメタデータはmd内にFront Matterで定義したものをgray-matterで取得している。
この記事だと以下のような定義。
--- title: "microCMSやめました" publishedAt: "2025-07-22T00:00:00.000Z" category: "Technology" ---
定義したメタデータは記事詳細の取得時にいい感じに整形して取り出している。
この辺も原型はclaude codeに投げて書いて貰っている。
const { data, content } = matter(fileContents); return { id, title: data.title, content: content, excerpt: extractExcerpt(content), category: { id: data.category.toLowerCase(), name: data.category, }, publishedAt: data.publishedAt, };
記事一覧の見出し部分はmarkdownファイルをそのまま書き出すと、コードブロックやら見出しの記号がそのまま見えてしまうので、テキストのみを出力するように整形してから文字数でのトリムをかけている。多分もっといい方法があると思うけど一旦は解決しているからそのままにしておく。
function extractExcerpt(content: string): string { // Markdownから最初のテキスト部分を抽出(見出しやコードブロックを除く) const textOnly = content .replace(/^#.*$/gm, "") // 見出しを除去 .replace(/```[\s\S]*?```/g, "") // コードブロックを除去 .replace(/`[^`]+`/g, "") // インラインコードを除去 .replace(/\*\*([^*]+)\*\*/g, "$1") // 太字マークダウンを除去 .replace(/\*([^*]+)\*/g, "$1") // イタリックを除去 .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1") // リンクを除去 .trim(); // 最初の段落(空行まで)を取得 const firstParagraph = textOnly.split("\n\n")[0]; // 100文字でトリムして省略記号を追加 if (firstParagraph.length > 100) { return firstParagraph.substring(0, 100) + "..."; } return firstParagraph; }
とりあえずこれでmicroCMSの依存は消せたので多少は開発しやすくなった気がする。 ローカルにmdファイル置いておけば後からどこにでも移行できるしやって良かったはず。