共通フォーマットのHTMLテンプレートファイルに対して、別で管理しているデータを流し込んで複数のHTMLファイルを一括で生成してみたいと思います。
実行環境
・Node.js 14.15
・Python 3.8
・Jinja
手順
- JSONデータの作成
- テンプレートHTMLの作成
- Pythonスクリプトの作成
- 実行
JSONデータの作成
JSONのデータは外部APIなどで取得してもよいのですが、今回はローカルで作成し、管理・運用がしやすいようにTypeScriptのオブジェクトから作成したいと思います。
// データの型定義ファイル
type Post = {
id: string;
date: string;
title: string;
author: string;
body: string;
};
export interface PageData {
filename: string;
meta: {
title: string;
description: string;
}
posts: Post[];
}
/data/pages
ディレクトリにそれぞれのページごとにデータを管理します。
sample-a.html
を管理するデータ
import { PageData } from '../../types';
export const sampleA: PageData = {
filename: 'sample-a.html',
meta: {
title: 'サンプルA',
description: 'サンプルAの説明文',
},
posts: [
{
id: '001',
date: '2021/01/01',
title: '初めての投稿',
author: 'いぬ',
body: 'hoge',
},
{
id: '002',
date: '2021/01/02',
title: '面白いタイトル!',
author: 'ねこ',
body: 'hogehoge',
}
]
}
sample-b.html
を管理するデータ
import { PageData } from '../../types';
export const sampleB: PageData = {
filename: 'sample-b.html',
meta: {
title: 'サンプルB',
description: 'サンプルBの説明文',
},
posts: [
{
id: '003',
date: '2021/01/05',
title: '心に残る映画',
author: 'いぬ',
body: '〇〇〇〇〇〇〇〇〇〇',
},
]
}
これらのTypeScriptオブジェクトを結合してJSONデータを生成します。
JSONデータを生成するためのスクリプトを書きます。
import { writeFile } from "fs"; // <- 事前に "yarn add -D fs" でモジュールをインストール
import { PageData } from "./types";
// データのインポート
import { sampleA } from "./data/pages/sample-a";
import { sampleB } from "./data/pages/sample-b";
// 配列に入れる
const data: PageData[] = [sampleA, sampleB];
// JSONデータのファイルとして書き出し
writeFile('data.json', JSON.stringify(data, null, " "), () => {});
これをJSにコンパイルしてNode.jsで実行します。
tsc script.ts
node script.js
これで data.json
が生成されます。
[
{
"filename": "sample-a.html",
"meta": {
"title": "サンプルA",
"description": "サンプルAの説明文"
},
"posts": [
{
"id": "001",
"date": "2021/01/01",
"title": "初めての投稿",
"author": "いぬ",
"body": "hoge"
},
{
"id": "002",
"date": "2021/01/02",
"title": "面白いタイトル!",
"author": "ねこ",
"body": "hogehoge"
}
]
},
{
"filename": "sample-b.html",
"meta": {
"title": "サンプルB",
"description": "サンプルBの説明文"
},
"posts": [
{
"id": "003",
"date": "2021/01/05",
"title": "心に残る映画",
"author": "いぬ",
"body": "〇〇〇〇〇〇〇〇〇〇"
}
]
}
]
テンプレートHTMLの作成
共通フォーマットのテンプレートHTMLを作成します。
テンプレートは Python のライブラリ Jinja2 で使用するので、Jinja2 の構文に従って作成します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ meta.title }}</title>
<meta name="description" content="{{ meta.description }}">
</head>
<body>
<h1>{{ meta.title }}</h1>
<div class="posts">
{% for post in posts %}
<div class="post" data-id="{{ post.id }}">
<div class="date">{{ post.date}}</div>
<h2 class="title">{{ post.title }}</h2>
<div class="author">{{ post.author }}</div>
<div class="body">{{ post.body }}</div>
</div>
{% endfor %}
</div>
</body>
</html>
作成した PageData
の型に従って、JSONから受け取ったデータを入れる変数を {{ }}
の中に記述します。
forループやif文などの制御構文は {% %}
の中に記述して使うことができます。
詳細については Jinja2 のページをご参照ください。
Pythonスクリプトの作成
データとテンプレートは出来上がったので、いよいよビルドするためのスクリプトをPythonで書いていきます。
まずは Jinja2 ライブラリをインストールします。
pip install jinja2
from jinja2 import Environment, FileSystemLoader
import json
import os
# 1.JSONからデータの読み込み
json_open = open('./data.json', 'r')
# データの格納された配列
items = json.load(json_open)
# 2.テンプレートファイルの読み込み
env = Environment(loader = FileSystemLoader('./templates'), autoescape = True)
template = env.get_template('page.html')
# 3.テンプレートにデータの流し込み
build_dir = 'dist'
# distディレクトリの存在を確認。なければ作成する
if not os.path.isdir(build_dir):
os.mkdir(build_dir)
# データ配列の数だけ実行
for item in items:
# テンプレートにデータを流し込んでHTMLを作成
parse_html = template.render(item)
# 保存先のパスを作成
path = f"{build_dir}/{item['filename']}"
# HTMLファイルの生成と保存
with open(path, 'w') as file:
file.write(parse_html)
ビルドの実行
python generate.py
これで、dist/
ディレクトリに目的のHTMLファイル(ここでは sample-a.html
と sample-b.html
)が生成されていれば完了です!
ソースコードはGitHubに載せています。
https://github.com/hiropy0123/python-html-generate