#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(lang, 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(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 #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(lang, info, uservars) = { align(center)[ = #info.personal.name #addresstext(lang, info, uservars) #contacttext(lang, info, uservars) ] } #let cvwork(lang, info, isbreakable: true) = { if info.experience != none {block[ == #info.experience.title #for w in info.experience.content { block(width: 100%, breakable: isbreakable)[ #if w.url != none [ *#link(w.url)[#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(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 education = info.education if education != none {block[ == #education.title #for edu in education.content { let start = utils.strpdate(lang, edu.startDate) let end = utils.strpdate(lang, edu.endDate) let eduurl = edu.at("url", default: none) // create a block layout for each education entry block(width: 100%, breakable: isbreakable)[ // line 1: institution and location #if eduurl != none [ *#link(eduurl)[#edu.with]* #h(1fr) *#edu.where* \ ] else [ *#edu.with* #h(1fr) *#edu.where* \ ] // line 2: degree and date #text(style: "italic")[#edu.what] #h(1fr) #start #sym.dash.en #end \ #for hi in edu.why [ - #eval(hi, 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(lang, info, isbreakable: true) = { block(breakable: isbreakable)[ == #info.skills.title #for skill in info.skills.content { [- *#skill.title*] } ] } #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]") ] ) }