130 lines
3.5 KiB
Python
Executable file
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()
|