🧾

Astroで記事のURLの末尾に.mdをつけたときに生のMarkdownで表示する

#

Astro

AstroのContent collectionで管理している記事のURLの末尾に.mdをつけた時にtext/markdownで返す方法について解説する。

##概要

Qiita や​ esa.io などで​搭載されている​記事の​末尾に​ .md つけると、​生の​ Markdown データを​取得できるように​する​機能を​ Astro で​実装します。

##環境

  • Astro: v5.15.1
  • Astro の​ Content Collections で​記事を​管理している​こと

##実際の​動き

  • /blog/example → 通常の​ HTML と​して​表示
  • /blog/example.mdtext/markdown 形式で​ Markdown の​生データを​表示

##ディレクトリ構成

当サイトでは​次のような​ディレクトリ構成で​記事を​管理しています。awardblogproduct と​複数の​コレクションが​あり、​これらを​一括で​処理する​行えるようにしました。

ディレクトリ構成
src/pages/
├─ award/
│ └─ [...slug].astro
├─ blog/
│ └─ [...slug].astro
└─ product/
└─ [...slug].astro

##エンドポイントの​実装

ここで​ src/pages/[collection]/[...slug].md.ts と​して​新しく​エンドポイント用の​ファイルを​作ります。

ディレクトリ構成
src/pages/
└─ [collection]/
└─ [...slug].md.ts ← Markdownで​返すエンドポイント

ディレクトリの​名前を​ [collection] に​する​ことで​動的パラメータを​用いて​複数の​コレクションを​一括で​処理できるようになります。

src/pages/[collection]/[...slug].md.ts
import { getAllPosts, type AllPost } from "@/utils/post";
export async function getStaticPaths() {
const entries = await getAllPosts();
return entries.map((entry) => ({
params: {
collection: entry.collection, // award, blog, product
slug: entry.data.slug,
},
props: { entry },
}));
}
export async function GET({ props }: { props: { entry: AllPost } }) {
const { entry } = props;
const markdown = entry.body;
return new Response(markdown, {
status: 200,
headers: {
// text/markdownと​して​設定
"Content-Type": "text/markdown; charset=utf-8",
"Cache-Control": "public, max-age=3600",
},
});
}

##おわりに

Astro の​動的ルーティングと​エンドポイント機能を​組み合わせる​ことで、​意外と​簡単に​実装できました。