diff --git a/docs/assets/images/EducationEntry.png b/docs/assets/images/EducationEntry.png deleted file mode 100644 index 6e60bbe..0000000 Binary files a/docs/assets/images/EducationEntry.png and /dev/null differ diff --git a/docs/assets/images/ExperienceEntry.png b/docs/assets/images/ExperienceEntry.png deleted file mode 100644 index eb221bd..0000000 Binary files a/docs/assets/images/ExperienceEntry.png and /dev/null differ diff --git a/docs/assets/images/NormalEntry.png b/docs/assets/images/NormalEntry.png deleted file mode 100644 index 20b7cfc..0000000 Binary files a/docs/assets/images/NormalEntry.png and /dev/null differ diff --git a/docs/assets/images/OneLineEntry.png b/docs/assets/images/OneLineEntry.png deleted file mode 100644 index 5b07d72..0000000 Binary files a/docs/assets/images/OneLineEntry.png and /dev/null differ diff --git a/docs/assets/images/PublicationEntry.png b/docs/assets/images/PublicationEntry.png deleted file mode 100644 index 12a3c08..0000000 Binary files a/docs/assets/images/PublicationEntry.png and /dev/null differ diff --git a/docs/assets/images/classic/education_entry.png b/docs/assets/images/classic/education_entry.png new file mode 100644 index 0000000..59df2aa Binary files /dev/null and b/docs/assets/images/classic/education_entry.png differ diff --git a/docs/assets/images/classic/experience_entry.png b/docs/assets/images/classic/experience_entry.png new file mode 100644 index 0000000..a3b4554 Binary files /dev/null and b/docs/assets/images/classic/experience_entry.png differ diff --git a/docs/assets/images/classic/normal_entry.png b/docs/assets/images/classic/normal_entry.png new file mode 100644 index 0000000..77e10f5 Binary files /dev/null and b/docs/assets/images/classic/normal_entry.png differ diff --git a/docs/assets/images/classic/one_line_entry.png b/docs/assets/images/classic/one_line_entry.png new file mode 100644 index 0000000..631c3ad Binary files /dev/null and b/docs/assets/images/classic/one_line_entry.png differ diff --git a/docs/assets/images/classic/publication_entry.png b/docs/assets/images/classic/publication_entry.png new file mode 100644 index 0000000..6ec30f1 Binary files /dev/null and b/docs/assets/images/classic/publication_entry.png differ diff --git a/docs/assets/images/classic/text_entry.png b/docs/assets/images/classic/text_entry.png new file mode 100644 index 0000000..09314cd Binary files /dev/null and b/docs/assets/images/classic/text_entry.png differ diff --git a/docs/assets/images/moderncv/education_entry.png b/docs/assets/images/moderncv/education_entry.png new file mode 100644 index 0000000..6b56af9 Binary files /dev/null and b/docs/assets/images/moderncv/education_entry.png differ diff --git a/docs/assets/images/moderncv/experience_entry.png b/docs/assets/images/moderncv/experience_entry.png new file mode 100644 index 0000000..b3f1fee Binary files /dev/null and b/docs/assets/images/moderncv/experience_entry.png differ diff --git a/docs/assets/images/moderncv/normal_entry.png b/docs/assets/images/moderncv/normal_entry.png new file mode 100644 index 0000000..771e156 Binary files /dev/null and b/docs/assets/images/moderncv/normal_entry.png differ diff --git a/docs/assets/images/moderncv/one_line_entry.png b/docs/assets/images/moderncv/one_line_entry.png new file mode 100644 index 0000000..2f0a30d Binary files /dev/null and b/docs/assets/images/moderncv/one_line_entry.png differ diff --git a/docs/assets/images/moderncv/publication_entry.png b/docs/assets/images/moderncv/publication_entry.png new file mode 100644 index 0000000..7049a29 Binary files /dev/null and b/docs/assets/images/moderncv/publication_entry.png differ diff --git a/docs/assets/images/moderncv/text_entry.png b/docs/assets/images/moderncv/text_entry.png new file mode 100644 index 0000000..dce6e79 Binary files /dev/null and b/docs/assets/images/moderncv/text_entry.png differ diff --git a/docs/assets/images/sb2nov/education_entry.png b/docs/assets/images/sb2nov/education_entry.png new file mode 100644 index 0000000..944cdaa Binary files /dev/null and b/docs/assets/images/sb2nov/education_entry.png differ diff --git a/docs/assets/images/sb2nov/experience_entry.png b/docs/assets/images/sb2nov/experience_entry.png new file mode 100644 index 0000000..f2ea840 Binary files /dev/null and b/docs/assets/images/sb2nov/experience_entry.png differ diff --git a/docs/assets/images/sb2nov/normal_entry.png b/docs/assets/images/sb2nov/normal_entry.png new file mode 100644 index 0000000..129d7c9 Binary files /dev/null and b/docs/assets/images/sb2nov/normal_entry.png differ diff --git a/docs/assets/images/sb2nov/one_line_entry.png b/docs/assets/images/sb2nov/one_line_entry.png new file mode 100644 index 0000000..487629d Binary files /dev/null and b/docs/assets/images/sb2nov/one_line_entry.png differ diff --git a/docs/assets/images/sb2nov/publication_entry.png b/docs/assets/images/sb2nov/publication_entry.png new file mode 100644 index 0000000..8c839f4 Binary files /dev/null and b/docs/assets/images/sb2nov/publication_entry.png differ diff --git a/docs/assets/images/sb2nov/text_entry.png b/docs/assets/images/sb2nov/text_entry.png new file mode 100644 index 0000000..02cb742 Binary files /dev/null and b/docs/assets/images/sb2nov/text_entry.png differ diff --git a/docs/contact.md b/docs/contact.md deleted file mode 100644 index a81e25d..0000000 --- a/docs/contact.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -hide: - - navigation ---- -test \ No newline at end of file diff --git a/docs/generate_entry_figures.py b/docs/generate_entry_figures.py new file mode 100644 index 0000000..3ee0342 --- /dev/null +++ b/docs/generate_entry_figures.py @@ -0,0 +1,227 @@ +import tempfile +import pathlib +import importlib +import importlib.machinery +import importlib.util +import io +from typing import Any + +import pdfCropMargins +import ruamel.yaml +import pypdfium2 + +# Import rendercv. I import the data_models and renderer modules like this instead +# of using `import rendercv` because in order for that to work, the current working +# directory must be the root of the project. To make it convenient for the user, I +# import the modules using the full path of the files. +rendercv_path = pathlib.Path(__file__).parent.parent / "rendercv" + +# Import the rendercv.data_models as dm: +spec = importlib.util.spec_from_file_location( + "rendercv.data_models", rendercv_path / "data_models.py" +) +dm = importlib.util.module_from_spec(spec) # type: ignore +spec.loader.exec_module(dm) # type: ignore + +# Import the rendercv.renderer as r: +spec = importlib.util.spec_from_file_location( + "rendercv.renderer", rendercv_path / "renderer.py" +) +r = importlib.util.module_from_spec(spec) # type: ignore +spec.loader.exec_module(r) # type: ignore + + +# The entries below will be pasted into the documentation as YAML, and their +# corresponding figures will be generated with this script. +education_entry = { + "institution": "Boğaziçi University", + "location": "Istanbul, Turkey", + "degree": "BS", + "area": "Mechanical Engineering", + "start_date": "2015-09", + "end_date": "2020-06", + "highlights": [ + "GPA: 3.24/4.00 ([Transcript](https://example.com))", + "Awards: Dean's Honor List, Sportsperson of the Year", + ], +} + +experience_entry = { + "company": "Some Company", + "location": "TX, USA", + "position": "Software Engineer", + "start_date": "2020-07", + "end_date": "2021-08-12", + "highlights": [ + ( + "Developed a [IOS application](https://example.com) that has recieved" + " more than **100,000 downloads**." + ), + "Managed a team of **5** engineers.", + ], +} + +normal_entry = { + "name": "Some Project", + "location": "Remote", + "date": "2021-09", + "highlights": [ + "Developed a web application with **React** and **Django**.", + "Implemented a **RESTful API**", + ], +} + +publication_entry = { + "title": ( + "Magneto-Thermal Thin Shell Approximation for 3D Finite Element Analysis of" + " No-Insulation Coils" + ), + "authors": ["John Doe", "Harry Tom"], + "date": "2023-12-08", + "journal": "IEEE Transactions on Applied Superconductivity", + "doi": "10.1109/TASC.2023.3340648", +} + +one_line_entry = { + "name": "Programming", + "details": "Python, C++, JavaScript, MATLAB", +} + +text_entry = ( + "This is a *TextEntry*. It is only a text and can be useful for sections like" + " **Summary**. To showcase the TextEntry completely, this sentence is added, but it" + " doesn't contain any information." +) + + +def dictionary_to_yaml(dictionary: dict[str, Any]): + """Converts a dictionary to a YAML string. + + Args: + dictionary (dict[str, Any]): The dictionary to be converted to YAML. + Returns: + str: The YAML string. + """ + yaml_object = ruamel.yaml.YAML() + with io.StringIO() as string_stream: + yaml_object.dump(dictionary, string_stream) + yaml_string = string_stream.getvalue() + return yaml_string + + +def define_env(env): + # see https://mkdocs-macros-plugin.readthedocs.io/en/latest/macros/ + entries = [ + "education_entry", + "experience_entry", + "normal_entry", + "publication_entry", + "one_line_entry", + "text_entry", + ] + + entries_showcase = dict() + for entry in entries: + proper_entry_name = entry.replace("_", " ").title() + entries_showcase[proper_entry_name] = { + "yaml": dictionary_to_yaml(eval(entry)), + "figures": [ + { + "path": f"assets/images/{theme}/{entry}.png", + "alt_text": f"{proper_entry_name} in {theme}", + "theme": theme, + } + for theme in dm.available_themes + ], + } + + env.variables["showcase_entries"] = entries_showcase + + +if __name__ == "__main__": + # Generate PDF figures for each entry type and theme + entries = { + "education_entry": dm.EducationEntry(**education_entry), + "experience_entry": dm.ExperienceEntry(**experience_entry), + "normal_entry": dm.NormalEntry(**normal_entry), + "publication_entry": dm.PublicationEntry(**publication_entry), + "one_line_entry": dm.OneLineEntry(**one_line_entry), + "text_entry": f'"{text_entry}', + } + themes = dm.available_themes + + pdf_assets_directory = pathlib.Path(__file__).parent / "assets" / "images" + + with tempfile.TemporaryDirectory() as temporary_directory: + # create a temporary directory: + temporary_directory_path = pathlib.Path(temporary_directory) + for theme in themes: + for entry_type, entry in entries.items(): + design_dictionary = { + "theme": theme, + "disable_page_numbering": True, + "show_last_updated_date": False, + } + if theme == "moderncv": + # moderncv theme does not support these options: + del design_dictionary["disable_page_numbering"] + del design_dictionary["show_last_updated_date"] + + # Create the data model with only one section and one entry + data_model = dm.RenderCVDataModel( + **{ + "cv": dm.CurriculumVitae(sections={entry_type: [entry]}), + "design": design_dictionary, + } + ) + + # Render: + latex_file_path = r.generate_latex_file_and_copy_theme_files( + data_model, temporary_directory_path + ) + pdf_file_path = r.latex_to_pdf(latex_file_path) + + # Prepare the output directory and file path: + output_directory = pdf_assets_directory / theme + output_directory.mkdir(parents=True, exist_ok=True) + output_pdf_file_path = output_directory / f"{entry_type}.pdf" + + # Remove the file if it exists: + if output_pdf_file_path.exists(): + output_pdf_file_path.unlink() + + # Crop the margins + pdfCropMargins.crop( + argv_list=[ + "-p4", + "100", + "0", + "100", + "0", + "-a4", + "0", + "-30", + "0", + "-30", + "-o", + str(output_pdf_file_path.absolute()), + str(pdf_file_path.absolute()), + ] + ) + + # Convert pdf to an image + image_name = output_pdf_file_path.with_suffix(".png") + pdf = pypdfium2.PdfDocument(str(output_pdf_file_path.absolute())) + page = pdf[0] + image = page.render(scale=5).to_pil() + + # If the image exists, remove it + if image_name.exists(): + image_name.unlink() + + image.save(image_name) + + pdf.close() + + # Remove the pdf file + output_pdf_file_path.unlink() diff --git a/docs/user_guide.md b/docs/user_guide.md index 619db36..579746a 100644 --- a/docs/user_guide.md +++ b/docs/user_guide.md @@ -1,5 +1,8 @@ # RenderCV: User Guide + + + After you've installed RenderCV with ```bash @@ -49,167 +52,15 @@ There are five entry types in RenderCV: 4. *OneLineEntry* 5. *PublicationEntry* -The whole CV consists of these entries. The table below shows what sections of the input file use which entry type. - -| YAML section | Entry Type | -| ------------------------------ | -------------------------------- | -| `education` | *EducationEntry* | -| `work_experience` | *ExperienceEntry* | -| `academic_projects` | *NormalEntry* | -| `publications` | *PublicationEntry* | -| `certificates` | *NormalEntry* | -| `skills` | *OneLineEntry* | -| `test_scores` | *OneLineEntry* | -| `personal_projects` | *NormalEntry* | -| `extracurricular_activities` | *ExperienceEntry* | -| `custom_sections` | **They can be any of the five!** | - -!!! info - Note that *EducationEntry* is not necessarily for education entries only. It's one of the five entry designs that RenderCV offers, and it could be used for anything (see [custom sections](http://user_guide.md#custom-sections)). *EducationEntry* just happens to be its name. The same goes for other entries, too. - -### *EducationEntry* +The whole CV consists of these entries. +{% for entry_name, entry in showcase_entries.items() %} +## {{ entry_name }} ```yaml -institution: Boğaziçi University -url: https://boun.edu.tr -area: Mechanical Engineering -degree: BS -location: Istanbul, Turkey -start_date: "2017-09-01" -end_date: "2023-01-01" -transcript_url: https://example.com -gpa: 3.10/4.00 -highlights: -- "Class rank: 10 of 62" - +{{ entry["yaml"] }} ``` - -which renders into - -![EducationEntry](assets/images/imagesEducationEntry.png) - -### *ExperienceEntry* - -```yaml -company: AmIACompany -position: Summer Intern -location: Istanbul, Turkey -url: https://example.com -start_date: "2022-06-15" -end_date: "2022-08-01" -highlights: -- AmIACompany is a technology company that provides web-based engineering - applications that enable the simulation and optimization of products and - manufacturing tools. -- Modeled and simulated a metal-forming process deep drawing using finite element - analysis with open-source software called CalculiX. -``` - -which renders into - -![ExperienceEntry](assets/images/imagesExperienceEntry.png) - -### *NormalEntry* - -```yaml -name: Design and Construction of a Dynamometer -location: Istanbul, Turkey -date: Fall 2022 -highlights: -- Designed and constructed a controllable dynamometer that measures an electric - motor's torque and power output at different speeds for my senior design project. -url: https://example.com - -``` - -which renders into - -![NormalEntry](assets/images/imagesNormalEntry.png) - -### *OneLineEntry* -```yaml -name: Programming -details: C++, C, Python, JavaScript, MATLAB, Lua, LaTeX -``` - -which renders into - -![OneLineEntry](assets/images/imagesOneLineEntry.png) - -### *PublicationEntry* - -```yaml -title: Phononic band gaps induced by inertial amplification in periodic media -authors: -- Author 1 -- John Doe -- Author 3 -journal: Physical Review B -doi: 10.1103/PhysRevB.76.054309 -date: "2007-08-01" -cited_by: 243 -``` - -which renders into - -![PublicationEntry](assets/images/imagesPublicationEntry.png) - - -## Custom Sections - -Custom sections with custom titles can be created. Each custom section will be an object that looks like this: - -```yaml -title: My Custom Section -entry_type: OneLineEntry -entries: -- name: Testing custom sections - details: Wohooo! -- name: This is a - details: OneLineEntry! -``` - -And `custom_sections` part of the data model will be a list of customs section objects that look like this: -```yaml -custom_sections: -- title: My Custom Section - entry_type: OneLineEntry - entries: - - name: Testing custom sections - details: Wohooo! - - name: This is a - details: OneLineEntry! -- title: My Other Custom Section - entry_type: EducationEntry - entries: - - institution: Hop! - area: Hop! - degree: HA - highlights: - - "There are only five types of entries: *EducationEntry*, *ExperienceEntry*, - *NormalEntry*, *OneLineEntry*, and *PublicationEntry*." - - This is an EducationEntry! - start_date: "2022-06-15" - end_date: "2022-08-01" -``` - -Each custom section needs to have an entry type, and entries should be adjusted according to the entry type selection. - -!!! note - - Some entry types use links, and all the links have a text placeholder. That placeholder can be changed with `link_text` setting as shown below: - ```yaml - title: My Third Custom Section - entry_type: ExperienceEntry - link_text: My Link Text - entries: - - company: Hop! - position: Hop! - date: My Date - location: My Location - url: https://example.com - highlights: - - I think this is really working. This is an *ExperienceEntry*! - ``` - - + {% for figure in entry["figures"] %} +`{{ figure["theme"] }}` theme: +![figure["alt_text"]]({{ figure["path"] }}) + {% endfor %} +{% endfor %} \ No newline at end of file diff --git a/mkdocs.yaml b/mkdocs.yaml index 27a8033..565206b 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -71,6 +71,8 @@ markdown_extensions: plugins: - search + - macros: # mkdocs-macros-plugin + module_name: docs/generate_entry_figures - mkdocstrings: handlers: python: