静的サイトジェネレータを作る

この記事はソフメアドベントカレンダー2021、1日目の記事です。

はじめに

みなさんこんにちは!みつばです!
毎年12月に行われているソフメアドベントカレンダーも今年で4回目の開催となりました!めでたい!

1日目の記事は、今日から12/24まで開催されるソフメアドベントカレンダーの諸々の作業をなるべく自動化しようとして、小さい静的サイトジェネレータを作ったお話をしたいと思います。
1日目からP班くらいにしか興味を持ってもらえなさそうな記事を書いてしまって申し訳ない限りです…

書いた人

HN : みつば
所属班 : プログラム班
回生 : 2回生
Twitter : @0508Maruyama

静的サイトジェネレータとは

テンプレートと書きたい内容を記述したファイルのセットを元にして、Webブラウザで見ることが出来るコンテンツを生成するようなツールの一般的な呼び名。
WordPressなどに代表されるコンテンツ管理システム(CSM)との大きな違いは、CSMがユーザーからアクセスされるたびに動的にコンテンツを生成して送信するのに対し、静的サイトジェネレータでは送信されるコンテンツは事前に生成された静的なものなので、高速にページが読み込まれるなどの違いがある。
[参考] : https://www.cloudflare.com/ja-jp/learning/performance/static-site-generator/

HTMLを手で書いたことがあるソフメ部員はきっと何人かはいると思いますが、手打ちのHTMLは動的生成コンテンツではなく静的なコンテンツに分類されます。
この静的なコンテンツを良い感じにテンプレートと、(HTMLを書くよりも楽な形式で書かれた)ページのデータを組み合わせて生成することが出来るのが、静的サイトジェネレータと呼ばれるツールです。
オープンソースの静的サイトジェネレータは色々あって、例えばJekyllHugoってやつが有名ですが、今回はそんなに規模が大きくなくて良いので最小限の機能を持つ静的サイトジェネレータを作ってみました。

欲しかった機能

欲しい機能を列挙するとこんな感じになりました。

  1. HTML以外で書かれたページデータをテンプレートと組み合わせてHTMLを生成する。
    →ページデータはMarkdownで書いてもらう。
  2. ページのタイトル、サムネイル画像なども良い感じに自動で書かれているようにしたい。
  3. 画像にはレスポンシブ対応用のタグをつけたい。
  4. HTMLは整形された状態のものを出力してほしい。

上にあげた項目を良い感じに実装すると、こんな成果物ができました。

成果物

GitHub - 32ba/markdown-to-html: Convert markdown to HTML using HTML templates
Convert markdown to HTML using HTML templates. Contribute to 32ba/markdown-to-html development by creating an account on GitHub.

中身はリポジトリ名の通り、Markdown形式で書かれたファイルをいい感じにHTMLファイルに変換するというプログラムをPythonで実装したものです。ここからは、どんな処理をやっているかについてお話ししたいと思います。

やったこと

1.Markdown→HTMLの変換

MarkdownからHTMLファイルを自動で生成できるようにPythonのライブラリであるmarkdownを使用し、MarkdownをHTMLに変換しています1
ちょうど、こんな感じのコードを書くと変数mdに入っているMarkdownがHTMLに変換されて標準出力に出力されます。

import markdown

md="""
# Hello world!
Markdown→HTMLのサンプル
"""

html = markdown.markdown(md)
print(html)

"""
出力

<h1>Hello world!</h1>
<p>Markdown→HTMLのサンプル</p>
"""

2.メタデータによる細かい部分の生成

ソフメアドベントカレンダーでは、記事執筆者の皆さんに以下のようなテンプレートを配布しました。

---
title : ""
author : ""
date : 2021-12-01
thumbnail : ""
---
<!--ここから本文-->

普通のMarkdownファイルには無いヘッダ部分があります。このヘッダはFront-matterと呼ばれる書式に沿っています。
これはHugoやJekyllに代表される大きな静的サイトジェネレータでも使われているような形式で、 Markdownの先頭にメタデータを書くことができます。 例えば、PythonのPython-frontmatterライブラリを使ってこんな感じのコードを書くと、メタデータをいい感じにプログラムから使えるようになります。

import frontmatter

"""
test.txtの中身

---
title : "テスト"
author : "みつば"
---
これは本文

"""

markdown=frontmatter.load('test.txt')
print("{} - {}".format(markdown["title"], markdown["title"]))
#出力 → テスト - みつば
print(markdown.content)
#出力 → これは本文

メタデータを使って、記事本体だけでなく細かい部分(ページタイトル、Twitter OGP、サムネイルなど)の生成を自動化しています。
また、ページデザインを変更する時にも、メタデータ付きの記事データがあれば簡単にページが作れると思います。
1と2で得られたデータをPythonのsting.Templateを使って雛形に組み込んで、表示できるHTMLファイルを作ることができました。

3.その他諸々

画像にレスポンシブ対応用のタグをつけたり、生成されるHTMLはインデントなどが崩れた状態だったので、HTML Tidyというツールで整形したりして綺麗なHTMLファイルを書き出しています。

時間があったらやりたい項目

時間が無さすぎて記事のHTMLファイルを生成すること以外が出来なかったが、時間があればこんな事もできると良いなぁ〜と思っています。

  • 画像ファイルを各記事ごとにディレクトリを作って仕分ける作業の自動化
    (例えば、12日目のimg1.jpgimg/12/img1.jpgみたいなディレクトリに勝手に仕分け出来てて欲しい)
  • コマンド1つでWebサーバに反映できるようにしたい

まとめ

今回はMarkdown形式のファイルをいい感じのHTML形式のファイルへ変換してくれるツールを作りました。 楽をするために苦労しているように感じますし、車輪の再開発っぽいことをしていますが、JekyllとかHugoとかの大きなツールと違って欲しい機能に限定した小さいツールを作ることで気軽に使えるようにはなったと思います。あとはカスタマイズが(Pythonさえ分かっていれば)簡単なのもいい点かなと思っています。

あとがき

ここまで記事を読んでくださり、ありがとうございました。
18日にも 『シェーダー沼に片足突っ込んでみた』 という題でUnityのシェーダーを書いてみた話と、Unityで沼にハマらずシェーダーに触れられる機能である シェーダーグラフ についての話2をしますので、そちらもよろしくお願いします。

次の記事は、ひとしさんで”VR入門”です。
自分もOculus Quest 2を持っているのですが、VRヘッドセットでしか得られない没入感がすごく面白いです。Beat SaberとVRChatにはめっちゃハマりました。


  1. MarkdownはHTMLを手軽に書くために生まれた言語であるので、この手のMarkdown→HTMLコンバータはどんな言語にも存在するはず 
  2. こっちがアドベントカレンダーで本当に書きたかった話(でも1日目には間に合わないので自動化っぽいことをして1本記事を書きました) 

コメント

タイトルとURLをコピーしました