diff --git a/rendercv/data_model.py b/rendercv/data_model.py index 3592a3a..ba47cc4 100644 --- a/rendercv/data_model.py +++ b/rendercv/data_model.py @@ -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 + # ====================================================================================== # ====================================================================================== diff --git a/rendercv/rendering.py b/rendercv/rendering.py index 72c67f1..9c97dee 100644 --- a/rendercv/rendering.py +++ b/rendercv/rendering.py @@ -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 diff --git a/rendercv/templates/classic.tex.j2 b/rendercv/templates/classic.tex.j2 index e115c9b..fc0046b 100644 --- a/rendercv/templates/classic.tex.j2 +++ b/rendercv/templates/classic.tex.j2 @@ -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[<>, a4paper]{article} % Packages: \usepackage[ ignoreheadfoot, % set margins without considering header and footer - top=<>, % seperation between body and page edge from the top - bottom=<>, % seperation between body and page edge from the bottom - left=<>, % seperation between body and page edge from the left - right=<>, % seperation between body and page edge from the right + top=<>, % seperation between body and page edge from the top + bottom=<>, % seperation between body and page edge from the bottom + left=<>, % seperation between body and page edge from the left + 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}{<>} % define primary color +\definecolor{primaryColor}{RGB}{<>} % 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{<>}[ Path= fonts/, Extension = .ttf, UprightFont = *-Regular, @@ -63,10 +63,10 @@ 0pt }{ % top space: - <> + <> }{ % bottom space: - <> + <> } % section title spacing \newcolumntype{L}[1]{ @@ -82,11 +82,11 @@ \newenvironment{highlights}{ \begin{itemize}[ topsep=0pt, - parsep=<>, + parsep=<>, partopsep=0pt, itemsep=0pt, after=\vspace*{-1\baselineskip}, - leftmargin=<> + 3pt + leftmargin=<> + 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 *)) diff --git a/rendercv/templates/components/classic/date_and_location_strings.tex.j2 b/rendercv/templates/components/classic/date_and_location_strings.tex.j2 index 768a81c..f563ee9 100644 --- a/rendercv/templates/components/classic/date_and_location_strings.tex.j2 +++ b/rendercv/templates/components/classic/date_and_location_strings.tex.j2 @@ -1,9 +1,9 @@ ((* macro date_and_location_strings(date_and_location_strings) *)) ((* for item in date_and_location_strings *)) ((* if loop.last *)) -<> \hspace*{-0.2cm + <>} +<> \hspace*{-0.2cm + <>} ((* else *)) -<> \hspace*{-0.2cm + <>} \newline +<> \hspace*{-0.2cm + <>} \newline ((* endif *)) ((* endfor *)) ((* endmacro *)) \ No newline at end of file diff --git a/rendercv/templates/components/classic/entry.tex.j2 b/rendercv/templates/components/classic/entry.tex.j2 index 4e55cef..ebf794d 100644 --- a/rendercv/templates/components/classic/entry.tex.j2 +++ b/rendercv/templates/components/classic/entry.tex.j2 @@ -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{<>}; variable width, ragged left column #)) - ((# third column: R{<>}; constant widthm ragged right column #)) -\begin{tabularx}{\textwidth}{p{0.55cm} K{<>} R{<>}} + ((# second column: K{<>}; variable width, ragged left column #)) + ((# third column: R{<>}; constant widthm ragged right column #)) +\begin{tabularx}{\textwidth}{p{0.55cm} K{<>} R{<>}} \textbf{<>} & \textbf{<>}, <> @@ -22,9 +22,9 @@ ((# \begin{tabularx}{⟨width⟩}[⟨pos⟩]{⟨preamble⟩} #)) ((# width: \textwidth #)) ((# preamble: first column, second column #)) - ((# first column:: K{<>}; variable width, ragged left column #)) - ((# second column: R{<>}; constant width ragged right column #)) -\begin{tabularx}{\textwidth}{K{<>} R{<>}} + ((# first column:: K{<>}; variable width, ragged left column #)) + ((# second column: R{<>}; constant width ragged right column #)) +\begin{tabularx}{\textwidth}{K{<>} R{<>}} \textbf{<>}, <> <> & @@ -36,9 +36,9 @@ ((# \begin{tabularx}{⟨width⟩}[⟨pos⟩]{⟨preamble⟩} #)) ((# width: \textwidth #)) ((# preamble: first column, second column #)) - ((# first column:: K{<>}; variable width, ragged left column #)) - ((# second column: R{<>}; constant width ragged right column #)) -\begin{tabularx}{\textwidth}{K{<>} R{<>}} + ((# first column:: K{<>}; variable width, ragged left column #)) + ((# second column: R{<>}; constant width ragged right column #)) +\begin{tabularx}{\textwidth}{K{<>} R{<>}} ((* 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{<>}; variable width, ragged left column #)) - ((# second column: R{<>}; constant width ragged right column #)) -\begin{tabularx}{\textwidth}{K{<>} R{2 cm}} + ((# first column:: K{<>}; variable width, ragged left column #)) + ((# second column: R{<>}; constant width ragged right column #)) +\begin{tabularx}{\textwidth}{K{<>} R{2 cm}} \textbf{<>} <<authors|join(", ")|make_it_italic(cv.name)>> diff --git a/rendercv/templates/components/classic/highlights.tex.j2 b/rendercv/templates/components/classic/highlights.tex.j2 index 122ecdf..11e1756 100644 --- a/rendercv/templates/components/classic/highlights.tex.j2 +++ b/rendercv/templates/components/classic/highlights.tex.j2 @@ -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} diff --git a/rendercv/templates/components/classic/section_contents.tex.j2 b/rendercv/templates/components/classic/section_contents.tex.j2 index 4dff102..589e907 100644 --- a/rendercv/templates/components/classic/section_contents.tex.j2 +++ b/rendercv/templates/components/classic/section_contents.tex.j2 @@ -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 *)) diff --git a/rendercv/templates/fonts/Roboto/Roboto-Bold.ttf b/rendercv/templates/fonts/Roboto/Roboto-Bold.ttf new file mode 100644 index 0000000..43da14d Binary files /dev/null and b/rendercv/templates/fonts/Roboto/Roboto-Bold.ttf differ diff --git a/rendercv/templates/fonts/Roboto/Roboto-BoldItalic.ttf b/rendercv/templates/fonts/Roboto/Roboto-BoldItalic.ttf new file mode 100644 index 0000000..bcfdab4 Binary files /dev/null and b/rendercv/templates/fonts/Roboto/Roboto-BoldItalic.ttf differ diff --git a/rendercv/templates/fonts/Roboto/Roboto-Italic.ttf b/rendercv/templates/fonts/Roboto/Roboto-Italic.ttf new file mode 100644 index 0000000..1b5eaa3 Binary files /dev/null and b/rendercv/templates/fonts/Roboto/Roboto-Italic.ttf differ diff --git a/rendercv/templates/fonts/Roboto/Roboto-Regular.ttf b/rendercv/templates/fonts/Roboto/Roboto-Regular.ttf new file mode 100644 index 0000000..ddf4bfa Binary files /dev/null and b/rendercv/templates/fonts/Roboto/Roboto-Regular.ttf differ