350 lines
11 KiB
Plaintext
350 lines
11 KiB
Plaintext
#import "utils.typ"
|
|
|
|
// set rules
|
|
#let setrules(uservars, doc) = {
|
|
set text(
|
|
font: uservars.bodyfont,
|
|
size: uservars.fontsize,
|
|
hyphenate: false,
|
|
)
|
|
|
|
set list(
|
|
spacing: uservars.linespacing
|
|
)
|
|
|
|
set par(
|
|
leading: uservars.linespacing,
|
|
justify: true,
|
|
)
|
|
|
|
doc
|
|
}
|
|
|
|
// show rules
|
|
#let showrules(uservars, doc) = {
|
|
// uppercase section headings
|
|
show heading.where(
|
|
level: 2,
|
|
): it => block(width: 100%)[
|
|
#set align(left)
|
|
#set text(font: uservars.headingfont, size: 1em, weight: "bold")
|
|
#if (uservars.at("headingsmallcaps", default:false)) {
|
|
smallcaps(it.body)
|
|
} else {
|
|
it.body
|
|
}
|
|
#v(-0.75em) #line(length: 100%, stroke: 1pt + black) // draw a line
|
|
]
|
|
|
|
// name title
|
|
show heading.where(
|
|
level: 1,
|
|
): it => block(width: 100%)[
|
|
#set text(font: uservars.headingfont, size: 2em, weight: "bold")
|
|
#if (uservars.at("headingsmallcaps", default:false)) {
|
|
smallcaps(it.body)
|
|
} else {
|
|
// upper(it.body)
|
|
it.body
|
|
}
|
|
#v(2pt)
|
|
]
|
|
|
|
doc
|
|
}
|
|
|
|
// set page layout
|
|
#let cvinit(doc) = {
|
|
doc = setrules(doc)
|
|
doc = showrules(doc)
|
|
|
|
doc
|
|
}
|
|
|
|
// address
|
|
#let addresstext(info, uservars) = {
|
|
if uservars.showAddress {
|
|
block(width: 100%)[
|
|
#info.personal.location.city, #info.personal.location.region, #info.personal.location.country
|
|
#v(-4pt)
|
|
]
|
|
} else {none}
|
|
}
|
|
|
|
#let fa(body) = {
|
|
set text(font:"FontAwesome")
|
|
[#body]
|
|
}
|
|
|
|
|
|
#let contacttext(info, uservars) = block(width: 100%)[
|
|
#let profiles = (
|
|
box(link("mailto:" + info.personal.email)[#fa(" ") #info.personal.email]),
|
|
if uservars.showNumber {box(link("tel:" + info.personal.phone)[#fa("") #info.personal.phone])} else {none},
|
|
if info.personal.url != none {
|
|
box(link(info.personal.url)[#fa(" ") #info.personal.url.split("//").at(1)])
|
|
}
|
|
).filter(it => it != none) // filter out none elements from the profile array
|
|
|
|
#if info.personal.profiles.len() > 0 {
|
|
for profile in info.personal.profiles {
|
|
profiles.push(
|
|
box(link(profile.url)[#profile.username])
|
|
)
|
|
}
|
|
}
|
|
|
|
#set text(font: uservars.bodyfont, weight: "light", size: uservars.fontsize * 1)
|
|
#pad(x: 0em)[
|
|
#profiles.join([#sym.space.en|#sym.space.en])
|
|
]
|
|
]
|
|
|
|
#let cvheading(info, uservars) = {
|
|
align(center)[
|
|
= #info.personal.name
|
|
#addresstext(info, uservars)
|
|
#contacttext(info, uservars)
|
|
]
|
|
}
|
|
|
|
#let cvwork(lang, info, isbreakable: true) = {
|
|
if info.experience != none {block[
|
|
== #utils.getWithLang(lang, info.experience.title)
|
|
#for w in info.experience.content {
|
|
let wwith = utils.getWithLang(lang, w.with)
|
|
let wwhere = utils.getWithLang(lang, w.where)
|
|
block(width: 100%, breakable: isbreakable)[
|
|
#if w.url != none [
|
|
*#link(utils.getWithLang(lang, w.url))[#wwith]* #h(1fr) *#wwhere* \
|
|
] else [
|
|
*#wwith* #h(1fr) *#wwhere* \
|
|
]
|
|
]
|
|
// create a block layout for each work entry
|
|
let index = 0
|
|
for p in w.what {
|
|
if index != 0 {v(0.6em)}
|
|
block(width: 100%, breakable: isbreakable, above: 0.6em)[
|
|
// parse ISO date strings into datetime objects
|
|
#let start = utils.strpdate(lang, p.startDate)
|
|
#let end = utils.strpdate(lang, p.endDate)
|
|
// line 2: position and date range
|
|
#text(style: "italic")[#utils.getWithLang(lang, p.what)] #h(1fr)
|
|
#start #sym.dash.en #end \
|
|
// highlights or description
|
|
#for hi in utils.getWithLang(lang, p.why) [
|
|
- #eval(utils.getWithLang(lang, hi), mode: "markup")
|
|
]
|
|
]
|
|
index = index + 1
|
|
}
|
|
}
|
|
]}
|
|
}
|
|
|
|
#let cveducation(lang, info, isbreakable: true) = {
|
|
if info.education != none {block[
|
|
== Education
|
|
#for edu in info.education {
|
|
let start = utils.strpdate(lang, edu.startDate)
|
|
let end = utils.strpdate(lang, edu.endDate)
|
|
|
|
let edu-items = ""
|
|
if edu.honors != none {edu-items = edu-items + "- *Honors*: " + edu.honors.join(", ") + "\n"}
|
|
if edu.why != none {edu-items = edu-items + "- *Courses*: " + edu.why.join(", ") + "\n"}
|
|
if edu.highlights != none {
|
|
for hi in edu.highlights {
|
|
edu-items = edu-items + "- " + hi + "\n"
|
|
}
|
|
edu-items = edu-items.trim("\n")
|
|
}
|
|
|
|
// create a block layout for each education entry
|
|
block(width: 100%, breakable: isbreakable)[
|
|
// line 1: institution and location
|
|
#if edu.url != none [
|
|
*#link(edu.url)[#edu.with]* #h(1fr) *#edu.what* \
|
|
] else [
|
|
*#edu.with* #h(1fr) *#edu.what* \
|
|
]
|
|
// line 2: degree and date
|
|
#text(style: "italic")[#edu.what] #h(1fr)
|
|
#start #sym.dash.en #end \
|
|
#eval(edu-items, mode: "markup")
|
|
]
|
|
}
|
|
]}
|
|
}
|
|
|
|
#let cvaffiliations(lang, info, isbreakable: true) = {
|
|
if info.affiliations != none {block[
|
|
== Leadership & Activities
|
|
#for org in info.affiliations {
|
|
// parse ISO date strings into datetime objects
|
|
let start = utils.strpdate(lang, org.startDate)
|
|
let end = utils.strpdate(lang, org.endDate)
|
|
|
|
// create a block layout for each affiliation entry
|
|
block(width: 100%, breakable: isbreakable)[
|
|
// line 1: organization and location
|
|
#if org.url != none [
|
|
*#link(org.url)[#org.with]* #h(1fr) *#org.where* \
|
|
] else [
|
|
*#org.with* #h(1fr) *#org.where* \
|
|
]
|
|
// line 2: position and date
|
|
#text(style: "italic")[#org.position] #h(1fr)
|
|
#start #sym.dash.en #end \
|
|
// highlights or description
|
|
#if org.highlights != none {
|
|
for hi in org.highlights [
|
|
- #eval(hi, mode: "markup")
|
|
]
|
|
} else {}
|
|
]
|
|
}
|
|
]}
|
|
}
|
|
|
|
#let cvprojects(lang, info, isbreakable: true) = {
|
|
if info.projects != none {block[
|
|
== Projects
|
|
#for project in info.projects {
|
|
// parse ISO date strings into datetime objects
|
|
let start = utils.strpdate(lang, project.startDate)
|
|
let end = utils.strpdate(lang, project.endDate)
|
|
// create a block layout for each project entry
|
|
block(width: 100%, breakable: isbreakable)[
|
|
// line 1: project name
|
|
#if project.url != none [
|
|
*#link(project.url)[#project.name]* \
|
|
] else [
|
|
*#project.name* \
|
|
]
|
|
// line 2: organization and date
|
|
#text(style: "italic")[#project.affiliation] #h(1fr) #start #sym.dash.en #end \
|
|
// summary or description
|
|
#for hi in project.highlights [
|
|
- #eval(hi, mode: "markup")
|
|
]
|
|
]
|
|
}
|
|
]}
|
|
}
|
|
|
|
#let cvawards(lang, info, isbreakable: true) = {
|
|
if info.awards != none {block[
|
|
== Honors & Awards
|
|
#for award in info.awards {
|
|
// parse ISO date strings into datetime objects
|
|
let date = utils.strpdate(lang, award.date)
|
|
// create a block layout for each award entry
|
|
block(width: 100%, breakable: isbreakable)[
|
|
// line 1: award title and location
|
|
#if award.url != none [
|
|
*#link(award.url)[#award.title]* #h(1fr) *#award.location* \
|
|
] else [
|
|
*#award.title* #h(1fr) *#award.location* \
|
|
]
|
|
// line 2: issuer and date
|
|
Issued by #text(style: "italic")[#award.issuer] #h(1fr) #date \
|
|
// summary or description
|
|
#if award.highlights != none {
|
|
for hi in award.highlights [
|
|
- #eval(hi, mode: "markup")
|
|
]
|
|
} else {}
|
|
]
|
|
}
|
|
]}
|
|
}
|
|
|
|
#let cvcertificates(lang, info, isbreakable: true) = {
|
|
if info.certificates != none {block[
|
|
== Licenses & Certifications
|
|
|
|
#for cert in info.certificates {
|
|
// parse ISO date strings into datetime objects
|
|
let date = utils.strpdate(lang, cert.date)
|
|
// create a block layout for each certificate entry
|
|
block(width: 100%, breakable: isbreakable)[
|
|
// line 1: certificate name
|
|
#if cert.url != none [
|
|
*#link(cert.url)[#cert.name]* \
|
|
] else [
|
|
*#cert.name* \
|
|
]
|
|
// line 2: issuer and date
|
|
Issued by #text(style: "italic")[#cert.issuer] #h(1fr) #date \
|
|
]
|
|
}
|
|
]}
|
|
}
|
|
|
|
#let cvpublications(lang, info, isbreakable: true) = {
|
|
if info.publications != none {block[
|
|
== Research & Publications
|
|
#for pub in info.publications {
|
|
// parse ISO date strings into datetime objects
|
|
let date = utils.strpdate(lang, pub.releaseDate)
|
|
// create a block layout for each publication entry
|
|
block(width: 100%, breakable: isbreakable)[
|
|
// line 1: publication title
|
|
#if pub.url != none [
|
|
*#link(pub.url)[#pub.name]* \
|
|
] else [
|
|
*#pub.name* \
|
|
]
|
|
// line 2: publisher and date
|
|
Published on #text(style: "italic")[#pub.publisher] #h(1fr) #date \
|
|
]
|
|
}
|
|
]}
|
|
}
|
|
|
|
#let cvskills(info, isbreakable: true) = {
|
|
if (info.languages != none) or (info.skills != none) or (info.interests != none) {block(breakable: isbreakable)[
|
|
== Skills, Languages, Interests
|
|
#if (info.languages != none) [
|
|
#let langs = ()
|
|
#for lang in info.languages {
|
|
langs.push([#lang.language (#lang.fluency)])
|
|
}
|
|
- *Languages*: #langs.join(", ")
|
|
]
|
|
#if (info.skills != none) [
|
|
#for group in info.skills [
|
|
- *#group.category*: #group.skills.join(", ")
|
|
]
|
|
]
|
|
#if (info.interests != none) [
|
|
- *Interests*: #info.interests.join(", ")
|
|
]
|
|
]}
|
|
}
|
|
|
|
#let cvreferences(info, isbreakable: true) = {
|
|
if info.references != none {block[
|
|
== References
|
|
#for ref in info.references {
|
|
block(width: 100%, breakable: isbreakable)[
|
|
#if ref.url != none [
|
|
- *#link(ref.url)[#ref.name]*: "#ref.reference"
|
|
] else [
|
|
- *#ref.name*: "#ref.reference"
|
|
]
|
|
]
|
|
}
|
|
]} else {}
|
|
}
|
|
|
|
#let endnote() = {
|
|
place(
|
|
bottom + right,
|
|
block[
|
|
#set text(size: 5pt, font: "Consolas", fill: silver)
|
|
Félix Desmaretz #datetime.today().display("[year]-[month]-[day]")
|
|
]
|
|
)
|
|
} |