FastAPIでDocusaurus風サイトを構築:ステップ2 - Markdownのレンダリング
James Reed
Infrastructure Engineer · Leapcell

前の記事では、FastAPIサービスをセットアップし、Jinja2を使用して動的なHTMLテンプレートをレンダリングしました。
しかし、他のドキュメンテーションサイトツールを使用したことがあるなら、それらのほとんどは手書きのHTMLではなく、Markdownで記述し、それをHTMLコンテンツの生成に使用していたことをご存知でしょう。
この記事では、この機能を正確に実装します。ローカルの.mdファイルを読み込み、HTMLに解析し、Webテンプレートに注入します。
ステップ1:Markdown解析ライブラリのインストール
MarkdownテキストをHTML文字列に変換するツールが必要です。このための一般的なライブラリはpython-markdownです。
以下のコマンドを実行してインストールしてください。
pip install markdown
ステップ2:最初のMarkdownドキュメントの作成
慣例により、すべてのソースドキュメントは新しいdocs/フォルダに保存します。
まず、プロジェクトのルートディレクトリにdocsフォルダを作成し、その中にhello.mdファイルを作成します。
更新されたプロジェクト構造:
fastapi-docs-site/
├── docs/               <-- 新規
│   └── hello.md        <-- 新規
├── main.py
├── static/
└── templates/
docs/hello.mdを編集:
この新しいファイルを開き、後でテストできるようにMarkdownコンテンツを記述します。
# Hello, Markdown! これはFastAPIでレンダリングされた最初のMarkdownドキュメントです。 コードブロックの例です(ただし、まだ構文ハイライトはありません): ```python def say_hello(): print("Hello from FastAPI!") ``` - これはリストアイテムです - これは別のリストアイテムです
ステップ3:ドキュメントレンダリング用テンプレートの作成
前回の記事で作成したtemplates/index.htmlはホームページです。ここでは、このMarkdownファイルのコンテンツを表示するための専用テンプレートが必要です。
templates/フォルダにdoc.htmlという名前の新しいファイルを作成します。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>{{ page_title }} - My Docs Site</title> </head> <body> <h1>{{ page_title }}</h1> <hr /> <div class="doc-content">{{ content | safe }}</div> </body> </html>
{{ content | safe }}はJinja2に「このcontent変数の内容は安全なHTMLです。直接レンダリングしてください。エスケープしないでください。」と伝えます。
ステップ4:Markdownレンダリングルートの作成
次に、main.pyを修正して、Markdownファイル用の新しいルートを追加しましょう。たとえば、/docs/helloです。
これは次のアクションを実行します。
docs/hello.mdファイルのコンテンツを読み込みます。markdownライブラリをインポートします。markdown.markdown()関数を使用して、ファイルの内容をHTML文字列に変換します。- このHTML文字列を
content変数としてdoc.htmlテンプレートに渡します。 
main.pyを開いて、以下のように修正します。
# main.py from fastapi import FastAPI, Request from fastapi.templating import Jinja2Templates from fastapi.responses import HTMLResponse import markdown # 1. markdownライブラリをインポート app = FastAPI() templates = Jinja2Templates(directory="templates") # --- 前回の記事のルートルーティング --- @app.get("/", response_class=HTMLResponse) async def root(request: Request): """ ルートルーティング、レンダリングされたHTMLテンプレートを返します """ context = { "request": request, "page_title": "Hello, Jinja2!" } return templates.TemplateResponse("index.html", context) # --- 2. 新しいドキュメンテーションルーティング --- @app.get("/docs/hello", response_class=HTMLResponse) async def get_hello_doc(request: Request): """ hello.mdドキュメントを読み込み、解析し、レンダリングします """ # 3. Markdownファイルのパスをハードコーディングします # (次の記事で動的にします) md_file_path = "docs/hello.md" try: with open(md_file_path, "r", encoding="utf-8") as f: md_content = f.read() except FileNotFoundError: # 簡単なエラー処理 return HTMLResponse(content="<h1>404 - Document not found</h1>", status_code=404) # 4. markdownライブラリを使用してHTMLに変換します html_content = markdown.markdown(md_content) # 5. テンプレートコンテキストを準備します # doc.htmlをレンダリングしていることに注意してください context = { "request": request, "page_title": "Hello, Markdown!", # 一時的にハードコーディングされたタイトル "content": html_content # 変換されたHTMLを渡します } return templates.TemplateResponse("doc.html", context)
ステップ5:実行とテスト
uvicorn main:app --reloadを実行してサーバーを起動します。
ブラウザでこのURLにアクセスしてください:http://127.0.0.1:8000/docs/hello
docs/hello.mdの内容がHTMLページとして正常にレンダリングされているはずです!

プロジェクトのオンラインデプロイ
ドキュメンテーションサイトは皆が訪問するためのものなので、ローカルで実行するだけでは不十分です。次に、オンラインでデプロイしましょう。
簡単なデプロイオプションはLeapcellを使用することです。Leapcellは、FastAPIを含むさまざまな言語やフレームワークのプロジェクトをホストできるWebアプリホスティングプラットフォームです。
以下の手順に従います。
1.ウェブサイトでアカウントを登録します。
2.プロジェクトをGitHubにコミットします。手順についてはGitHubの公式ドキュメントを参照してください。Leapcellは後でGitHubリポジトリからコードを取得します。
3.Leapcellページで「Create Service」をクリックします。

4.FastAPIリポジトリを選択すると、Leapcellが必要な構成を自動入力していることがわかります。

5.下部にある「Submit」をクリックしてデプロイします。デプロイはすぐに完了し、デプロイメントホームページに戻ります。ここで、Leapcellがドメインを提供していることがわかります。これがブログのオンラインアドレスです。

まとめと次のステップ
この記事で、ドキュメンテーションサイトの最もコアな機能である動的なMarkdown-to-HTML変換を実装しました。
hello.mdのPythonコードブロックに気づいたかもしれません。正しくコードとしてレンダリングされましたが、プレーンで色がなく、読みにくいです。
これは明らかにドキュメンテーションサイトに期待される体験ではありません。
次の記事では、この問題を解決します。レンダリングされたMarkdownコードブロックに構文ハイライトを追加します。
