html-cv/cvbuild.py

130 lines
3.5 KiB
Python
Executable file

#!/usr/bin/env python3
"""Build a CV in HTML with JSON data."""
import argparse
import json
import jinja2
def main() -> None:
"""Load the JSON content and inject it in a HTML template."""
args = parse_args()
files = {
"template": "out.html.j2",
"html_output": f"out.{args.language}.html",
"css_file": "css/styles.css",
"pdf_output": "out.pdf",
"meta": "data/meta.json",
"education": "data/education.json",
"experience": "data/experience.json",
}
meta: dict = load_json(files["meta"])
education: list[dict] = load_json(files["education"])
experience: list[dict] = load_json(files["experience"])
for key, value in meta.items():
try:
meta[key] = value[args.language]
except (KeyError, TypeError):
pass
for item in education:
for key, value in item.items():
try:
item[key] = value[args.language]
except (KeyError, TypeError):
pass
for item in experience:
for key, value in item.items():
try:
item[key] = value[args.language]
except (KeyError, TypeError):
pass
meta["assets"] = htmlify_json_element(meta["assets"])
meta["languages"] = htmlify_json_element(meta["languages"])
meta["skills"] = htmlify_json_element(meta["skills"])
education = [item for item in education if item["select"]]
experience = [item for item in experience if item["select"]]
for item in education:
item["date"] = set_date(item)
for item in experience:
item["date"] = set_date(item)
env = jinja2.Environment(
loader=jinja2.FileSystemLoader(""),
trim_blocks=True,
lstrip_blocks=True,
)
template = env.get_template(files["template"])
injected_template: str = template.render(
lang=args.language, meta=meta, education=education, experience=experience
)
with open(files["html_output"], "w", encoding="utf8") as output_file:
output_file.write(injected_template)
def load_json(filename: str):
"""Load data from a file and return its content."""
with open(filename, "r", encoding="utf8") as json_file:
json_dict: list[dict] | dict = json.load(json_file)
return json_dict
def htmlify_json_element(element: list[str] | dict[str, list[str]]) -> str:
"""Turn a JSON element into an string ready for HTML.
The element can be a list or a dict.
"""
if isinstance(element, list):
return "</p><p>".join(element)
output = ""
for element_str, element_list in element.items():
output += f"<p>{element_str}</p>\n"
output += "<ul>\n<li>\n"
output += "</li>\n<li>".join(element_list)
output += "</li>\n</ul>\n"
return output
def set_date(item: dict) -> str:
"""Use an item's day, month and year fields to format a date string."""
if item["day"]:
return f"{item['day']} {item['month']} {item['year']}"
if item["month"]:
return f"{item['month']} {item['year']}"
return f"{item['year']}"
def parse_args() -> argparse.Namespace:
"""Parse command line arguments"""
parser = argparse.ArgumentParser(
description="Build a CV in HTML by injecting json values in a template."
)
parser.add_argument(
"language",
choices=("fr", "en"),
help="Language to use for the CV"
)
return parser.parse_args()
if __name__ == "__main__":
main()