update docs
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 103 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 92 KiB |
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 101 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 106 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 69 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 92 KiB |
After Width: | Height: | Size: 73 KiB |
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
hide:
|
||||
- navigation
|
||||
---
|
||||
test
|
|
@ -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()
|
|
@ -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 %}
|
|
@ -71,6 +71,8 @@ markdown_extensions:
|
|||
|
||||
plugins:
|
||||
- search
|
||||
- macros: # mkdocs-macros-plugin
|
||||
module_name: docs/generate_entry_figures
|
||||
- mkdocstrings:
|
||||
handlers:
|
||||
python:
|
||||
|
|