Add Languages

master
Félix Desmaretz 2024-01-26 00:06:26 +01:00
parent 6863eda281
commit 3bfa1222e4
2 changed files with 331 additions and 285 deletions

561
cv/cv.typ
View File

@ -2,331 +2,374 @@
// set rules // set rules
#let setrules(uservars, doc) = { #let setrules(uservars, doc) = {
set text( set text(font: uservars.bodyfont, size: uservars.fontsize, hyphenate: false)
font: uservars.bodyfont,
size: uservars.fontsize,
hyphenate: false,
)
set list( set list(spacing: uservars.linespacing)
spacing: uservars.linespacing
)
set par( set par(leading: uservars.linespacing, justify: true)
leading: uservars.linespacing,
justify: true,
)
doc doc
} }
// show rules // show rules
#let showrules(uservars, doc) = { #let showrules(uservars, doc) = {
// uppercase section headings // uppercase section headings
show heading.where( show heading.where(level: 2): it => block(width: 100%)[
level: 2, #set align(left)
): it => block(width: 100%)[ #set text(font: uservars.headingfont, size: 1em, weight: "bold")
#set align(left) #if (uservars.at("headingsmallcaps", default: false)) {
#set text(font: uservars.headingfont, size: 1em, weight: "bold") smallcaps(it.body)
#if (uservars.at("headingsmallcaps", default:false)) { } else {
smallcaps(it.body) it.body
} else { }
it.body #v(-0.75em) #line(length: 100%, stroke: 1pt + black) // draw a line
} ]
#v(-0.75em) #line(length: 100%, stroke: 1pt + black) // draw a line
]
// name title // name title
show heading.where( show heading.where(level: 1): it => block(width: 100%)[
level: 1, #set text(font: uservars.headingfont, size: 2em, weight: "bold")
): it => block(width: 100%)[ #if (uservars.at("headingsmallcaps", default: false)) {
#set text(font: uservars.headingfont, size: 2em, weight: "bold") smallcaps(it.body)
#if (uservars.at("headingsmallcaps", default:false)) { } else {
smallcaps(it.body) // upper(it.body)
} else { it.body
// upper(it.body) }
it.body #v(2pt)
} ]
#v(2pt)
]
doc doc
} }
// set page layout // set page layout
#let cvinit(doc) = { #let cvinit(doc) = {
doc = setrules(doc) doc = setrules(doc)
doc = showrules(doc) doc = showrules(doc)
doc doc
} }
// address // address
#let addresstext(lang, info, uservars) = { #let addresstext(lang, info, uservars) = {
if uservars.showAddress { if uservars.showAddress {
block(width: 100%)[ block(
#info.personal.location.city, #info.personal.location.region, #info.personal.location.country width: 100%,
#v(-4pt) )[
] #info.personal.location.city, #info.personal.location.region, #info.personal.location.country
} else {none} #v(-4pt)
]
} else { none }
} }
#let fa(body) = { #let fa(body) = {
set text(font:"FontAwesome") set text(font: "FontAwesome")
[#body] [#body]
} }
#let contacttext(lang, 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.at("url", default: none) != 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
#let contacttext(lang, info, uservars) = block(width: 100%)[ #if info.personal.profiles.len() > 0 {
#let profiles = ( for profile in info.personal.profiles {
box(link("mailto:" + info.personal.email)[#fa(" ") #info.personal.email]), profiles.push(box(link(profile.url)[#profile.username]))
if uservars.showNumber {box(link("tel:" + info.personal.phone)[#fa("") #info.personal.phone])} else {none},
if info.personal.at("url", default: none) != 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) #set text(font: uservars.bodyfont, weight: "light", size: uservars.fontsize * 1)
#pad(x: 0em)[ #pad(x: 0em)[
#profiles.join([#sym.space.en|#sym.space.en]) #profiles.join([#sym.space.en|#sym.space.en])
] ]
] ]
#let cvheading(lang, info, uservars) = { #let cvheading(lang, info, uservars) = {
align(center)[ align(center)[
= #info.personal.name = #info.personal.name
#addresstext(lang, info, uservars) #addresstext(lang, info, uservars)
#contacttext(lang, info, uservars) #contacttext(lang, info, uservars)
] ]
} }
#let cvwork(lang, info, isbreakable: true) = { #let cvwork(lang, info, isbreakable: true) = {
if info.experience != none {block[ if info.experience != none {
== #info.experience.title block[
#for w in info.experience.content { == #info.experience.title
block(width: 100%, breakable: isbreakable)[ #for w in info.experience.content {
#if w.url != none [ block(width: 100%, breakable: isbreakable)[
*#link(w.url)[#w.with]* #h(1fr) *#w.where* \ #if w.url != none [
] else [ *#link(w.url)[#w.with]* #h(1fr) *#w.where* \
*#w.with* #h(1fr) *#w.where* \ ] else [
] *#w.with* #h(1fr) *#w.where* \
]
]
// 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(weight: "semibold", size: 9.0pt, fill: luma(30.6%))[#p.what #h(1fr)
#start #sym.dash.en #end] \
// highlights or description
#for hi in p.why [
- #text(weight: "light")[#eval(hi, mode: "markup")]
] ]
// create a block layout for each work entry ]
let index = 0 index = index + 1
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")[#p.what] #h(1fr)
#start #sym.dash.en #end \
// highlights or description
#for hi in p.why [
- #eval(hi, mode: "markup")
]
]
index = index + 1
}
} }
]} }
]
}
} }
#let cveducation(lang, info, isbreakable: true) = { #let cveducation(lang, info, isbreakable: true) = {
let education = info.education let education = info.education
if education != none {block[ if education != none {
== #education.title block[
#for edu in education.content { == #education.title
let start = utils.strpdate(lang, edu.startDate) #for edu in education.content {
let end = utils.strpdate(lang, edu.endDate) let start = utils.strpdate(lang, edu.startDate)
let eduurl = edu.at("url", default: none) let end = utils.strpdate(lang, edu.endDate)
let eduurl = edu.at("url", default: none)
// create a block layout for each education entry // create a block layout for each education entry
block(width: 100%, breakable: isbreakable)[ block(
// line 1: institution and location width: 100%,
#if eduurl != none [ breakable: isbreakable,
*#link(eduurl)[#edu.with]* #h(1fr) *#edu.where* \ )[
] else [ // line 1: institution and location
*#edu.with* #h(1fr) *#edu.where* \ #if eduurl != none {
] text(weight: "extrabold")[
// line 2: degree and date #link(eduurl)[#edu.with] #h(1fr) #edu.where \
#text(style: "italic")[#edu.what] #h(1fr)
#start #sym.dash.en #end \
#for hi in edu.why [
- #eval(hi, mode: "markup")
]
] ]
} } else {
]} text(weight: "extrabold")[
#edu.with #h(1fr) #edu.where \
]
}
// line 2: degree and date
#text(weight: "semibold", size: 9.0pt, fill: luma(30.6%))[#edu.what #h(1fr)
#start #sym.dash.en #end] \
#for hi in edu.why [
- #text(weight: "light")[#eval(hi, mode: "markup")]
]
]
}
]
}
} }
#let cvaffiliations(lang, info, isbreakable: true) = { #let cvaffiliations(lang, info, isbreakable: true) = {
if info.affiliations != none {block[ if info.affiliations != none {
== Leadership & Activities block[
#for org in info.affiliations { == Leadership & Activities
// parse ISO date strings into datetime objects #for org in info.affiliations {
let start = utils.strpdate(lang, org.startDate) // parse ISO date strings into datetime objects
let end = utils.strpdate(lang, org.endDate) let start = utils.strpdate(lang, org.startDate)
let end = utils.strpdate(lang, org.endDate)
// create a block layout for each affiliation entry // create a block layout for each affiliation entry
block(width: 100%, breakable: isbreakable)[ block(width: 100%, breakable: isbreakable)[
// line 1: organization and location // line 1: organization and location
#if org.url != none [ #if org.url != none [
*#link(org.url)[#org.with]* #h(1fr) *#org.where* \ *#link(org.url)[#org.with]* #h(1fr) *#org.where* \
] else [ ] else [
*#org.with* #h(1fr) *#org.where* \ *#org.with* #h(1fr) *#org.where* \
] ]
// line 2: position and date // line 2: position and date
#text(style: "italic")[#org.position] #h(1fr) #text(style: "italic")[#org.position] #h(1fr)
#start #sym.dash.en #end \ #start #sym.dash.en #end \
// highlights or description // highlights or description
#if org.highlights != none { #if org.highlights != none {
for hi in org.highlights [ for hi in org.highlights [
- #eval(hi, mode: "markup") - #eval(hi, mode: "markup")
]
} else {}
] ]
} } else {}
]} ]
}
]
}
} }
#let cvprojects(lang, info, isbreakable: true) = { #let cvprojects(lang, info, isbreakable: true) = {
if info.projects != none {block[ if info.projects != none {
== Projects block[
#for project in info.projects { == Projects
// parse ISO date strings into datetime objects #for project in info.projects {
let start = utils.strpdate(lang, project.startDate) // parse ISO date strings into datetime objects
let end = utils.strpdate(lang, project.endDate) let start = utils.strpdate(lang, project.startDate)
// create a block layout for each project entry let end = utils.strpdate(lang, project.endDate)
block(width: 100%, breakable: isbreakable)[ // create a block layout for each project entry
// line 1: project name block(
#if project.url != none [ width: 100%,
*#link(project.url)[#project.name]* \ breakable: isbreakable,
] else [ )[
*#project.name* \ // line 1: project name
] #if project.url != none [
// line 2: organization and date *#link(project.url)[#project.name]* \
#text(style: "italic")[#project.affiliation] #h(1fr) #start #sym.dash.en #end \ ] else [
// summary or description *#project.name* \
#for hi in project.highlights [ ]
- #eval(hi, mode: "markup") // 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) = { #let cvawards(lang, info, isbreakable: true) = {
if info.awards != none {block[ if info.awards != none {
== Honors & Awards block[
#for award in info.awards { == Honors & Awards
// parse ISO date strings into datetime objects #for award in info.awards {
let date = utils.strpdate(lang, award.date) // parse ISO date strings into datetime objects
// create a block layout for each award entry let date = utils.strpdate(lang, award.date)
block(width: 100%, breakable: isbreakable)[ // create a block layout for each award entry
// line 1: award title and location block(width: 100%, breakable: isbreakable)[
#if award.url != none [ // line 1: award title and location
*#link(award.url)[#award.title]* #h(1fr) *#award.location* \ #if award.url != none [
] else [ *#link(award.url)[#award.title]* #h(1fr) *#award.location* \
*#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 \ // line 2: issuer and date
// summary or description Issued by #text(style: "italic")[#award.issuer] #h(1fr) #date \
#if award.highlights != none { // summary or description
for hi in award.highlights [ #if award.highlights != none {
- #eval(hi, mode: "markup") for hi in award.highlights [
] - #eval(hi, mode: "markup")
} else {}
] ]
} } else {}
]} ]
}
]
}
} }
#let cvcertificates(lang, info, isbreakable: true) = { #let cvcertificates(lang, info, isbreakable: true) = {
if info.certificates != none {block[ if info.certificates != none {
== Licenses & Certifications block[
== Licenses & Certifications
#for cert in info.certificates { #for cert in info.certificates {
// parse ISO date strings into datetime objects // parse ISO date strings into datetime objects
let date = utils.strpdate(lang, cert.date) let date = utils.strpdate(lang, cert.date)
// create a block layout for each certificate entry // create a block layout for each certificate entry
block(width: 100%, breakable: isbreakable)[ block(width: 100%, breakable: isbreakable)[
// line 1: certificate name // line 1: certificate name
#if cert.url != none [ #if cert.url != none [
*#link(cert.url)[#cert.name]* \ *#link(cert.url)[#cert.name]* \
] else [ ] else [
*#cert.name* \ *#cert.name* \
] ]
// line 2: issuer and date // line 2: issuer and date
Issued by #text(style: "italic")[#cert.issuer] #h(1fr) #date \ Issued by #text(style: "italic")[#cert.issuer] #h(1fr) #date \
] ]
} }
]} ]
}
} }
#let cvpublications(lang, info, isbreakable: true) = { #let cvpublications(lang, info, isbreakable: true) = {
if info.publications != none {block[ if info.publications != none {
== Research & Publications block[
#for pub in info.publications { == Research & Publications
// parse ISO date strings into datetime objects #for pub in info.publications {
let date = utils.strpdate(lang, pub.releaseDate) // parse ISO date strings into datetime objects
// create a block layout for each publication entry let date = utils.strpdate(lang, pub.releaseDate)
block(width: 100%, breakable: isbreakable)[ // create a block layout for each publication entry
// line 1: publication title block(width: 100%, breakable: isbreakable)[
#if pub.url != none [ // line 1: publication title
*#link(pub.url)[#pub.name]* \ #if pub.url != none [
] else [ *#link(pub.url)[#pub.name]* \
*#pub.name* \ ] else [
] *#pub.name* \
// line 2: publisher and date ]
Published on #text(style: "italic")[#pub.publisher] #h(1fr) #date \ // line 2: publisher and date
] Published on #text(style: "italic")[#pub.publisher] #h(1fr) #date \
} ]
]} }
]
}
}
#let cvlanguages(lang, info, isbreakable: true) = {
block(breakable: isbreakable)[
== #info.languages.title
#for lang in info.languages.content {
[- *#lang.title*#text(weight: "light")[: #lang.content]]
}
]
} }
#let cvskills(lang, info, isbreakable: true) = { #let cvskills(lang, info, isbreakable: true) = {
block(breakable: isbreakable)[ block(
== #info.skills.title breakable: isbreakable,
)[
== #info.skills.title
#for skill in info.skills.content { #for skill in info.skills.content {
[- *#skill.title*] let skillContent = skill.content.sorted(key: x => {
} if type(x) == dictionary {
] x.keys().first()
} else { x }
}).map(
x => {
if type(x) == dictionary {
[#x.keys().first() (#text(style: "italic")[#x.values().first().sorted().join(", ")])]
} else {
[#x]
}
},
).join(", ")
[- *#skill.title*#text(weight: "light")[: #skillContent]]
}
]
} }
#let cvreferences(info, isbreakable: true) = { #let cvreferences(info, isbreakable: true) = {
if info.references != none {block[ if info.references != none {
== References block[
#for ref in info.references { == References
block(width: 100%, breakable: isbreakable)[ #for ref in info.references {
#if ref.url != none [ block(width: 100%, breakable: isbreakable)[
- *#link(ref.url)[#ref.name]*: "#ref.reference" #if ref.url != none [
] else [ - *#link(ref.url)[#ref.name]*: "#ref.reference"
- *#ref.name*: "#ref.reference" ] else [
] - *#ref.name*: "#ref.reference"
] ]
} ]
]} else {} }
]
} else {}
} }
#let endnote() = { #let endnote() = {
place( place(bottom + right, block[
bottom + right, #set text(size: 5pt, font: "Consolas", fill: silver)
block[ Félix Desmaretz #datetime.today().display("[year]-[month]-[day]")
#set text(size: 5pt, font: "Consolas", fill: silver) ])
Félix Desmaretz #datetime.today().display("[year]-[month]-[day]")
]
)
} }

View File

@ -1,48 +1,51 @@
#import "cv/cv.typ": * #import "cv/cv.typ": *
#import "cv/utils.typ"
#let language = "en" #let language = "fr"
#let cvdata = ( #let cvdata = utils.filterLanguage(language, (
personal: yaml(("data/", "en", "/personal.yaml").join()), personal: yaml(("data/", "en", "/personal.yaml").join()),
experience: yaml(("data/", "en", "/experience.yaml").join()), experience: yaml(("data/", "en", "/experience.yaml").join()),
education: yaml(("data/", "en", "/education.yaml").join()), education: yaml(("data/", "en", "/education.yaml").join()),
skills: yaml(("data/", "en", "/skills.yaml").join()) skills: yaml(("data/", "en", "/skills.yaml").join()),
) languages: yaml("data/en/languages.yaml"),
))
#let uservars = ( #let uservars = (
headingfont: "Roboto", headingfont: "Roboto",
bodyfont: "Roboto", bodyfont: "Roboto",
fontsize: 10pt, // 10pt, 11pt, 12pt fontsize: 10pt, // 10pt, 11pt, 12pt
linespacing: 6pt, linespacing: 6pt,
showAddress: true, // true/false show address in contact info showAddress: true, // true/false show address in contact info
showNumber: true, // true/false show phone number in contact info showNumber: true, // true/false show phone number in contact info
headingsmallcaps: false headingsmallcaps: false,
) )
#let customrules(doc) = { #let customrules(doc) = {
// add custom document style rules here // add custom document style rules here
set page( set page(
paper: "a4", // a4, us-letter paper: "a4", // a4, us-letter
// numbering: "1 / 1", // numbering: "1 / 1",
number-align: center, // left, center, right number-align: center, // left, center, right
margin: 1.25cm, // 1.25cm, 1.87cm, 2.5cm margin: 1.25cm, // 1.25cm, 1.87cm, 2.5cm
) )
doc doc
} }
#let cvinit(doc) = { #let cvinit(doc) = {
doc = setrules(uservars, doc) doc = setrules(uservars, doc)
doc = showrules(uservars, doc) doc = showrules(uservars, doc)
doc = customrules(doc) doc = customrules(doc)
doc doc
} }
#show: doc => cvinit(doc) #show: doc => cvinit(doc)
#cvheading(cvdata, uservars) #cvheading(language, cvdata, uservars)
#cvwork(language, cvdata) #cvwork(language, cvdata)
// #cveducation(cvdata) #cveducation(language, cvdata)
// #cvskills(cvdata) #cvlanguages(language, cvdata)
#cvskills(language, cvdata)
#endnote() #endnote()