Bauke/cv
Bauke
/
cv
1
Fork 0

Compare commits

...

3 Commits

Author SHA1 Message Date
Bauke acf0cf26e8
Add the DATA.md file. 2024-01-20 17:56:33 +01:00
Bauke 79c79d647a
Add the main Typst entrypoint. 2024-01-20 17:44:14 +01:00
Bauke e58397a59f
Add the main header component. 2024-01-20 17:43:23 +01:00
3 changed files with 204 additions and 0 deletions

93
DATA.md Normal file
View File

@ -0,0 +1,93 @@
# CV Data
A full example of the expected information at `data/info.toml` needed to render this CV template.
```toml
email = "address@example.org"
home_address = "Street 12, 2345 City"
name = "FirstName LastName"
phone_number = "+32 123 45 67 89"
experience_body = """[
Typst body to run through `eval()` and render inside the
experience section.
]"""
# Additional items to add for localization.
[locale]
dutch_en = "Dutch"
dutch_nl = "Nederlands"
email_en = "Email address"
email_nl = "E-mailadres"
english_en = "English"
english_nl = "Engels"
experience_en = "Experience"
experience_nl = "Ervaring"
forgejo = "Forgejo"
general_en = "General"
general_nl = "Algemeen"
github = "GitHub"
home_en = "Home address"
home_nl = "Thuisadres"
language_en = "Languages"
language_nl = "Talenkennis"
personal_projects_en = "Personal Projects"
personal_projects_nl = "Persoonlijke Projecten"
phone_en = "Phone number"
phone_nl = "Telefoonnummer"
platforms_en = "Platforms"
platforms_nl = "Platformen"
skills_en = "Skills"
skills_nl = "Vaardigheden"
software = "Software"
# Links to show in the header.
[links]
forgejo = "https://example.org"
github = "https://example.org"
[paths]
# The path for the image to use in the header.
header_image = "data/header-image.jpg"
[[personal_projects]]
# An optional header image to use in the section title.
header_image = "data/example.png"
# A link to the project's website or main page.
link = "https://example.org"
# The name of the project, can be localized.
name = "Project Name"
# The date of when the project started and/or ended, localizable.
date = "January 2024"
# The main body to be included, will be evaluated so you can
# write Typst code and is localizable.
body_en = """[
An #link("https://example.org", "example")!
]"""
body_nl = """[
Een #link("https://example.org", "voorbeeld")!
]"""
# To add more personal projects, add more tables:
# [[personal_projects]]
# ...
[[skills.language]]
# The color to use for the progress bar, will be evaluated
color = "orange"
# Localizable name for the skill.
name_en = "Dutch"
name_nl = "Nederlands"
# Percentage amount to fill the progress bar with.
proficiency = 100
# The available skill sections are:
# [[skills.language]]
# ...
# [[skills.general]]
# ...
# [[skills.software]]
# ...
# [[skills.platforms]]
# ...
```

64
components/header.typ Normal file
View File

@ -0,0 +1,64 @@
#import "../utilities/icon-with-text.typ": icon_with_text
#import "../utilities/localize.typ": localize
#let header(data, language, include_links, image_size: 6em, margin_size: 1em) = {
let info_section = {
block(
// Set the height explicitly so it fills the container properly.
height: 100%,
stroke: (bottom: 1pt + black),
align(
horizon,
// Use a 2x2 grid for the name and personal information.
grid(
columns: (1fr, 1fr),
row-gutter: 0.5em,
heading(data.name),
..("email", "home", "phone").map(info_key => icon_with_text(
icon: "../images/" + info_key + ".svg",
icon_alt_text: localize(data, info_key, language),
localize(data, info_key, language),
)),
),
),
)
}
let links_section = if include_links {
let link_keys = data.links.keys()
// Use a block to explicitly grow the size to fill the container.
block(height: 100%, width: 100%, align(
horizon,
// Then use a grid to layout the links with equal spacing in between.
grid(
columns: link_keys.len(),
column-gutter: 0.5em,
// Render the any links with their icons.
..link_keys.map(link_key => icon_with_text(
icon: "../images/" + link_key + ".svg",
icon_alt_text: localize(data, link_key, language),
link(data.links.at(link_key), localize(data, link_key, language)),
)),
),
))
}
// Position the header image to the right of the main header content.
grid(
columns: (1fr, image_size),
grid(
// Space the rows out so the first is two-thirds of the image size and the
// second is the remaining third.
rows: (image_size * 67%, image_size * 33%),
info_section,
links_section,
),
// Use a box to round off the corners of the image.
box(
clip: true,
radius: image_size / 4,
image("../" + data.paths.header_image, height: image_size),
),
)
}

47
main.typ Normal file
View File

@ -0,0 +1,47 @@
#import "./components/experience.typ": experience_section
#import "./components/personal-projects.typ": personal_projects_section
#import "./components/skills.typ": skills_section
#import "./components/header.typ": header
#import "./utilities/content-to-string.typ": content_to_string
#let cv(include_links: true, language: "") = {
if language == "" {
panic("No language option specified.")
}
let data = toml("data/info.toml")
set document(
author: data.name,
title: content_to_string([CV #data.name (#language)]),
)
set text(font: "Inter", lang: language, size: 12pt)
// The links color and styling has to be done this way because the `show`
// keyword only applies to the scope of the block it is in. Meaning it won't
// apply globally when put inside the `if` block.
let links = if include_links {
(color: rgb("#000080"), style: underline)
} else {
(color: black, style: (body) => body)
}
show link: set text(links.color)
show link: links.style
header(data, language, include_links)
// Portion out the main body using a grid.
grid(
columns: (60%, 40%),
gutter: 1.5em,
// Place the Experience and Personal Projects sections vertically in the
// left column of the grid.
{
experience_section(data, language)
personal_projects_section(data, language)
},
// And the Skills section in the right column.
skills_section(data, language),
)
}