add custom fonts support

This commit is contained in:
Sina Atalay 2023-10-08 15:41:20 +02:00
parent 3bf176f689
commit 8790097351
11 changed files with 76 additions and 45 deletions

View File

@ -13,6 +13,7 @@ import re
import logging
from functools import cached_property
import urllib.request
import os
from pydantic import (
BaseModel,
@ -409,12 +410,48 @@ class Design(BaseModel):
title="Theme name",
description='The only option is "Classic" for now.',
)
font: Literal["SourceSans3", "Roboto"] = Field(
default="SourceSans3",
title="Font",
description="The font of the CV.",
examples=["SourceSans3", "Roboto"],
)
font_size: Literal["10pt", "11pt", "12pt"] = Field(
default="10pt",
title="Font Size",
description="The font size of the CV. It can be 10pt, 11pt, or 12pt.",
examples=["10pt", "11pt", "12pt"],
)
options: ClassicThemeOptions = Field(
default=ClassicThemeOptions(),
title="Theme Options",
description="The options of the theme.",
)
@field_validator("font")
@classmethod
def check_font(cls, font: str) -> str:
# Go to fonts directory and check if the font exists:
fonts_directory = os.path.join(os.path.dirname(__file__), "templates", "fonts")
if font not in os.listdir(fonts_directory):
raise ValueError(
f'The font "{font}" is not found in the "fonts" directory! To add a new'
" font, please see TO BE ADDED."
)
else:
font_directory = os.path.join(fonts_directory, font)
required_files = [
f"{font}-Bold.ttf",
f"{font}-BoldItalic.ttf",
f"{font}-Italic.ttf",
f"{font}-Regular.ttf",
]
for file in required_files:
if file not in os.listdir(font_directory):
raise ValueError(f"{file} is not found in the {font} directory!")
return font
# ======================================================================================
# ======================================================================================

View File

@ -202,13 +202,13 @@ def print_today() -> str:
return today.strftime("%B %d, %Y")
def get_path_to_fonts_directory() -> str:
def get_path_to_font_directory(font_name: str) -> str:
"""Return the path to the fonts directory.
Returns:
str: The path to the fonts directory.
"""
return os.path.join(os.path.dirname(__file__), "templates", "fonts")
return os.path.join(os.path.dirname(__file__), "templates", "fonts", font_name)
def render_template(data):
@ -252,10 +252,10 @@ def render_template(data):
environment.filters["make_it_italic"] = make_it_italic
output_latex_file = template.render(
design=data.design.options,
cv=data.cv,
design=data.design,
theme_options=data.design.options,
today=print_today(),
fonts_directory=get_path_to_fonts_directory(),
)
# Create an output file and write the rendered LaTeX code to it:
@ -265,19 +265,13 @@ def render_template(data):
file.write(output_latex_file)
# Copy the fonts directory to the output directory:
fonts_directory = get_path_to_fonts_directory()
font_directory = get_path_to_font_directory(data.design.font)
output_fonts_directory = os.path.join(os.path.dirname(output_file_path), "fonts")
os.makedirs(output_fonts_directory, exist_ok=True)
for directory in os.listdir(fonts_directory):
if directory == "SourceSans3":
# copy the SourceSans3 fonts:
source_directory = os.path.join(fonts_directory, directory)
shutil.copytree(
source_directory,
output_fonts_directory,
dirs_exist_ok=True,
)
shutil.copytree(
font_directory,
output_fonts_directory,
dirs_exist_ok=True,
)
return output_file_path

View File

@ -2,15 +2,15 @@
((* from "components/classic/section_contents.tex.j2" import section_contents with context *))
((* from "components/classic/header.tex.j2" import header with context *))
\documentclass[10pt, a4paper]{article}
\documentclass[<<design.font_size>>, a4paper]{article}
% Packages:
\usepackage[
ignoreheadfoot, % set margins without considering header and footer
top=<<design.margins.page.top>>, % seperation between body and page edge from the top
bottom=<<design.margins.page.bottom>>, % seperation between body and page edge from the bottom
left=<<design.margins.page.left>>, % seperation between body and page edge from the left
right=<<design.margins.page.right>>, % seperation between body and page edge from the right
top=<<theme_options.margins.page.top>>, % seperation between body and page edge from the top
bottom=<<theme_options.margins.page.bottom>>, % seperation between body and page edge from the bottom
left=<<theme_options.margins.page.left>>, % seperation between body and page edge from the left
right=<<theme_options.margins.page.right>>, % seperation between body and page edge from the right
% showframe % for debugging
]{geometry} % for adjusting page geometry
\usepackage{fontspec} % for loading fonts
@ -18,7 +18,7 @@
\usepackage{tabularx} % for making tables with fixed width columns
\usepackage{array} % tabularx requires this
\usepackage[dvipsnames]{xcolor} % for coloring text
\definecolor{primaryColor}{RGB}{<<design.primary_color.as_rgb_tuple()|join(", ")>>} % define primary color
\definecolor{primaryColor}{RGB}{<<theme_options.primary_color.as_rgb_tuple()|join(", ")>>} % define primary color
\usepackage{enumitem} % for customizing lists
\usepackage{fontawesome5} % for using icons
\usepackage[
@ -38,7 +38,7 @@
\pagenumbering{gobble} % no page numbering
\setmainfont{SourceSans3}[
\setmainfont{<<design.font>>}[
Path= fonts/,
Extension = .ttf,
UprightFont = *-Regular,
@ -63,10 +63,10 @@
0pt
}{
% top space:
<<design.margins.section_title.top>>
<<theme_options.margins.section_title.top>>
}{
% bottom space:
<<design.margins.section_title.bottom>>
<<theme_options.margins.section_title.bottom>>
} % section title spacing
\newcolumntype{L}[1]{
@ -82,11 +82,11 @@
\newenvironment{highlights}{
\begin{itemize}[
topsep=0pt,
parsep=<<design.margins.highlights_area.vertical_between_bullet_points>>,
parsep=<<theme_options.margins.highlights_area.vertical_between_bullet_points>>,
partopsep=0pt,
itemsep=0pt,
after=\vspace*{-1\baselineskip},
leftmargin=<<design.margins.highlights_area.left>> + 3pt
leftmargin=<<theme_options.margins.highlights_area.left>> + 3pt
]
}{
\end{itemize}
@ -108,7 +108,7 @@
\newcommand{\hrefExternal}[2]{\href{#1}{#2\, \raisebox{.1ex}{\footnotesize \faExternalLink*}}} % new command for external links
\begin{document}
((* if design.show_last_updated_date *))
((* if theme_options.show_last_updated_date *))
\placelastupdatedtext
((* endif *))

View File

@ -1,9 +1,9 @@
((* macro date_and_location_strings(date_and_location_strings) *))
((* for item in date_and_location_strings *))
((* if loop.last *))
<<item>> \hspace*{-0.2cm + <<design.margins.entry_area.right>>}
<<item>> \hspace*{-0.2cm + <<theme_options.margins.entry_area.right>>}
((* else *))
<<item>> \hspace*{-0.2cm + <<design.margins.entry_area.right>>} \newline
<<item>> \hspace*{-0.2cm + <<theme_options.margins.entry_area.right>>} \newline
((* endif *))
((* endfor *))
((* endmacro *))

View File

@ -6,9 +6,9 @@
((# width: \textwidth #))
((# preamble: first column, second column, third column #))
((# first column: p{0.55cm}; constant width, ragged left column #))
((# second column: K{<<design.margins.entry_area.left>>}; variable width, ragged left column #))
((# third column: R{<<design.date_and_location_width>>}; constant widthm ragged right column #))
\begin{tabularx}{\textwidth}{p{0.55cm} K{<<design.margins.entry_area.left>>} R{<<design.date_and_location_width>>}}
((# second column: K{<<theme_options.margins.entry_area.left>>}; variable width, ragged left column #))
((# third column: R{<<theme_options.date_and_location_width>>}; constant widthm ragged right column #))
\begin{tabularx}{\textwidth}{p{0.55cm} K{<<theme_options.margins.entry_area.left>>} R{<<theme_options.date_and_location_width>>}}
\textbf{<<study_type if study_type is not none>>}
&
\textbf{<<institution>>}, <<area>>
@ -22,9 +22,9 @@
((# \begin{tabularx}{⟨width⟩}[⟨pos⟩]{⟨preamble⟩} #))
((# width: \textwidth #))
((# preamble: first column, second column #))
((# first column:: K{<<design.margins.entry_area.left>>}; variable width, ragged left column #))
((# second column: R{<<design.date_and_location_width>>}; constant width ragged right column #))
\begin{tabularx}{\textwidth}{K{<<design.margins.entry_area.left>>} R{<<design.date_and_location_width>>}}
((# first column:: K{<<theme_options.margins.entry_area.left>>}; variable width, ragged left column #))
((# second column: R{<<theme_options.date_and_location_width>>}; constant width ragged right column #))
\begin{tabularx}{\textwidth}{K{<<theme_options.margins.entry_area.left>>} R{<<theme_options.date_and_location_width>>}}
\textbf{<<company>>}, <<position>>
<<print_higlights(highlights)|indent(4)->>
&
@ -36,9 +36,9 @@
((# \begin{tabularx}{⟨width⟩}[⟨pos⟩]{⟨preamble⟩} #))
((# width: \textwidth #))
((# preamble: first column, second column #))
((# first column:: K{<<design.margins.entry_area.left>>}; variable width, ragged left column #))
((# second column: R{<<design.date_and_location_width>>}; constant width ragged right column #))
\begin{tabularx}{\textwidth}{K{<<design.margins.entry_area.left>>} R{<<design.date_and_location_width>>}}
((# first column:: K{<<theme_options.margins.entry_area.left>>}; variable width, ragged left column #))
((# second column: R{<<theme_options.date_and_location_width>>}; constant width ragged right column #))
\begin{tabularx}{\textwidth}{K{<<theme_options.margins.entry_area.left>>} R{<<theme_options.date_and_location_width>>}}
((* if markdown_url is not none *))
((* if link_text is not none *))
((* set markdown_url = "["+link_text+"]("+ markdown_url|markdown_url_to_url +")" *))
@ -59,9 +59,9 @@
((# \begin{tabularx}{⟨width⟩}[⟨pos⟩]{⟨preamble⟩} #))
((# width: \textwidth #))
((# preamble: first column, second column #))
((# first column:: K{<<design.margins.entry_area.left>>}; variable width, ragged left column #))
((# second column: R{<<design.date_and_location_width>>}; constant width ragged right column #))
\begin{tabularx}{\textwidth}{K{<<design.margins.entry_area.left>>} R{2 cm}}
((# first column:: K{<<theme_options.margins.entry_area.left>>}; variable width, ragged left column #))
((# second column: R{<<theme_options.date_and_location_width>>}; constant width ragged right column #))
\begin{tabularx}{\textwidth}{K{<<theme_options.margins.entry_area.left>>} R{2 cm}}
\textbf{<<title>>}
<<authors|join(", ")|make_it_italic(cv.name)>>

View File

@ -1,5 +1,5 @@
((* macro highlights(highlights) *))
\vspace*{<<design.margins.highlights_area.top>>}
\vspace*{<<theme_options.margins.highlights_area.top>>}
((* for item in highlights *))
((* if loop.first *))
\begin{highlights}

View File

@ -12,7 +12,7 @@
date_and_location_strings=date_and_location_strings
)|indent(4)>>
((* elif entry_type == "ExperienceEntry" *))
((* if design.show_timespan_in_experience_entries *))
((* if theme_options.show_timespan_in_experience_entries *))
((* set date_and_location_strings = value.date_and_location_strings_with_timespan *))
((* endif *))
<<entry["experience"](
@ -47,7 +47,7 @@
)|indent(4)>>
((* endif *))
((* if not loop.last *))
\vspace*{<<design.margins.entry_area.vertical_between>>}
\vspace*{<<theme_options.margins.entry_area.vertical_between>>}
((* endif *))
((* endfor *))

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.