I would like to generate multiple HTML files at once by pouring data managed separately into the HTML template file of the common format.
・ Node.js 14.15 -Python 3.8 ・ Jinja
JSON data may be obtained using an external API, but this time I would like to create it locally and create it from a TypeScript object for easy management and operation.
types/index.ts
//Data type definition file
type Post = {
id: string;
date: string;
title: string;
author: string;
body: string;
};
export interface PageData {
filename: string;
meta: {
title: string;
description: string;
}
posts: Post[];
}
Manage data for each page in the / data/pages
directory.
Data that manages sample-a.html
/data/pages/sample-a.ts
import { PageData } from '../../types';
export const sampleA: PageData = {
filename: 'sample-a.html',
meta: {
title: 'Sample A',
description: 'Description of sample A',
},
posts: [
{
id: '001',
date: '2021/01/01',
title: 'First post',
author: 'Dog',
body: 'hoge',
},
{
id: '002',
date: '2021/01/02',
title: 'Interesting title!',
author: 'Cat',
body: 'hogehoge',
}
]
}
Data that manages sample-b.html
/data/pages/sample-b.ts
import { PageData } from '../../types';
export const sampleB: PageData = {
filename: 'sample-b.html',
meta: {
title: 'Sample B',
description: 'Description of sample B',
},
posts: [
{
id: '003',
date: '2021/01/05',
title: 'A memorable movie',
author: 'Dog',
body: '〇〇〇〇〇〇〇〇〇〇',
},
]
}
Combine these TypeScript objects to generate JSON data.
Write a script to generate JSON data.
script.ts
import { writeFile } from "fs"; // <-Beforehand"yarn add -D fs"Install the module with
import { PageData } from "./types";
//Data import
import { sampleA } from "./data/pages/sample-a";
import { sampleB } from "./data/pages/sample-b";
//Put in an array
const data: PageData[] = [sampleA, sampleB];
//Export as a JSON data file
writeFile('data.json', JSON.stringify(data, null, " "), () => {});
Compile this into JS and run it in Node.js.
tsc script.ts
node script.js
This will generate data.json
.
data.json
[
{
"filename": "sample-a.html",
"meta": {
"title": "Sample A",
"description": "Description of sample A"
},
"posts": [
{
"id": "001",
"date": "2021/01/01",
"title": "First post",
"author": "Dog",
"body": "hoge"
},
{
"id": "002",
"date": "2021/01/02",
"title": "Interesting title!",
"author": "Cat",
"body": "hogehoge"
}
]
},
{
"filename": "sample-b.html",
"meta": {
"title": "Sample B",
"description": "Description of sample B"
},
"posts": [
{
"id": "003",
"date": "2021/01/05",
"title": "A memorable movie",
"author": "Dog",
"body": "〇〇〇〇〇〇〇〇〇〇"
}
]
}
]
Create template HTML in common format. Templates are used in the Python library Jinja2, so create them according to Jinja2 syntax.
templates/page.html
<!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>
According to the type of PageData
created, describe the variable that contains the data received from JSON in{{}}
.
Control syntax such as for loops and if statements can be written and used in {%%}
.
Please refer to the Jinja2 page for details.
Now that the data and template are complete, it's time to write the script to build in Python.
First, install the Jinja2 library.
pip install jinja2
generate.py
from jinja2 import Environment, FileSystemLoader
import json
import os
# 1.Read data from JSON
json_open = open('./data.json', 'r')
#Array of data
items = json.load(json_open)
# 2.Loading template file
env = Environment(loader = FileSystemLoader('./templates'), autoescape = True)
template = env.get_template('page.html')
# 3.Fill the template with data
build_dir = 'dist'
#Check for the existence of the dist directory. If not, create
if os.path.isdir(build_dir) == False:
os.mkdir(build_dir)
#Execute as many times as there are data arrays
for item in items:
#Create HTML by pouring data into a template
parse_html = template.render(item)
#Create a destination path
path = f"{build_dir}/{item['filename']}"
#Generate and save HTML files
with open(path, 'w') as file:
file.write(parse_html)
python generate.py
Now, if the desired HTML files (here sample-a.html
and sample-b.html
) are generated in the dist /
directory, you're done!
The source code is on GitHub. https://github.com/hiropy0123/python-html-generate
Recommended Posts