2023-11-30 15:11:59 +01:00
|
|
|
#let color = blue
|
|
|
|
// #let color = rgb("#018d32")
|
|
|
|
|
2023-11-27 16:04:11 +01:00
|
|
|
// Basic template settings. Must be shown at very begining
|
|
|
|
#let init(doc) = {
|
2023-11-30 11:36:16 +01:00
|
|
|
|
|
|
|
let opacity = "33" // opacity hex chars
|
|
|
|
|
|
|
|
let polymny = read("./assets/polymny.svg")
|
|
|
|
let polymny_transparent = polymny
|
|
|
|
.replace("#FFFFFFFF", "#FFFFFF" + opacity)
|
|
|
|
.replace("#EAE2D4FF", "#EAE2D4" + opacity)
|
|
|
|
.replace("#BDB299FF", "#BDB299" + opacity)
|
|
|
|
|
2023-11-27 15:40:19 +01:00
|
|
|
set page(
|
|
|
|
paper: "a4",
|
|
|
|
numbering: none,
|
|
|
|
margin: (left: 0.25cm, right: 0.25cm, top: 0.5cm, bottom: 0.5cm),
|
|
|
|
background: [
|
2023-11-30 11:36:16 +01:00
|
|
|
#place(bottom + left, dx: 2cm, dy: 2.75cm, {
|
|
|
|
image.decode(polymny_transparent, width: 65em, height: 65em)
|
|
|
|
})
|
|
|
|
|
2023-11-30 15:11:59 +01:00
|
|
|
#place(top + left, rect(width: 5.55cm, height: 100%, fill: color.lighten(90%)))
|
|
|
|
#place(top + left, rect(width: 100%, height: 4.4cm, fill: color))
|
2023-11-30 11:36:16 +01:00
|
|
|
#place(top + left, dx: 0.8cm, dy: 1cm, image("./assets/moi.png", height: 4cm))
|
2023-11-27 15:40:19 +01:00
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
set text(font: "CMU Sans Serif")
|
|
|
|
set par(leading: 0.4em)
|
|
|
|
|
2023-11-27 16:04:11 +01:00
|
|
|
doc
|
|
|
|
}
|
|
|
|
|
|
|
|
// Template for the left column. Must be shown before filling the left column content.
|
|
|
|
#let leftColumn(doc) = {
|
|
|
|
set text(size: 12pt)
|
|
|
|
|
|
|
|
show link: content => {
|
|
|
|
underline(content)
|
|
|
|
}
|
|
|
|
|
|
|
|
show heading.where(level: 1): it => {
|
|
|
|
v(0.75cm)
|
|
|
|
text(size: 16pt, weight: "bold", it.body)
|
|
|
|
v(-0.5cm)
|
|
|
|
line(length: 5cm)
|
|
|
|
}
|
|
|
|
|
|
|
|
doc
|
|
|
|
}
|
|
|
|
|
|
|
|
// Template for the rest of the CV. Must be shown after the left column is done.
|
|
|
|
#let content(doc) = {
|
|
|
|
|
2023-11-27 18:52:43 +01:00
|
|
|
show link: content => {
|
|
|
|
set text(fill: blue)
|
|
|
|
underline(content)
|
|
|
|
}
|
|
|
|
|
2023-11-27 15:40:19 +01:00
|
|
|
show heading.where(level: 1): it => {
|
2023-11-30 15:11:59 +01:00
|
|
|
set text(fill: color)
|
2023-11-27 15:40:19 +01:00
|
|
|
grid(
|
|
|
|
gutter: 1em,
|
|
|
|
columns: (5cm, 7fr),
|
2023-11-30 15:11:59 +01:00
|
|
|
[], // align(horizon, [#v(3pt) #rect(width: 1cm, height: 0.33em, fill: color)]),
|
2023-11-27 15:40:19 +01:00
|
|
|
[
|
|
|
|
#it.body
|
|
|
|
#v(-0.5cm)
|
2023-11-30 15:11:59 +01:00
|
|
|
#line(stroke: color, length: 100%)
|
2023-11-27 15:40:19 +01:00
|
|
|
],
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
doc
|
|
|
|
}
|
|
|
|
|
2023-11-27 16:04:11 +01:00
|
|
|
// Print the header of the CV.
|
|
|
|
#let header(name: content, description: content) = {
|
|
|
|
v(1cm)
|
|
|
|
grid(
|
|
|
|
columns: (6cm, 1fr),
|
|
|
|
|
|
|
|
[],
|
|
|
|
|
|
|
|
[
|
|
|
|
#v(-0.25cm)
|
|
|
|
#set text(size: 40pt, fill: white)
|
|
|
|
Thomas Forgione \
|
|
|
|
#set text(size: 18pt, style: "italic")
|
|
|
|
Docteur en informatique et télécommunications
|
|
|
|
],
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// A simple entry in the CV.
|
2023-11-27 15:40:19 +01:00
|
|
|
#let entry(body, left: content) = {
|
|
|
|
grid(
|
|
|
|
gutter: 1em,
|
|
|
|
columns: (5.5cm, 0.75fr, 7fr),
|
|
|
|
[],
|
|
|
|
align(right, left),
|
|
|
|
body,
|
|
|
|
)
|
|
|
|
v(-4pt)
|
|
|
|
}
|
|
|
|
|
2023-11-27 16:04:11 +01:00
|
|
|
// An entry in the CV with "until" date, heading, description and note.
|
2024-01-11 15:31:17 +01:00
|
|
|
#let entry2(left: content, heading: content, description: content, note: content, disable_line: false) = {
|
2023-11-27 15:40:19 +01:00
|
|
|
|
|
|
|
let content = [
|
2023-11-30 15:11:59 +01:00
|
|
|
#heading \
|
|
|
|
#set text(size: 12pt, style: "italic")
|
|
|
|
#description \
|
|
|
|
#set text(size: 11pt, style: "normal")
|
|
|
|
#note
|
|
|
|
]
|
|
|
|
|
|
|
|
layout(size =>
|
2023-11-27 15:40:19 +01:00
|
|
|
style(styles => {
|
2023-11-30 15:11:59 +01:00
|
|
|
let size = measure({
|
|
|
|
block(
|
|
|
|
width: size.width,
|
|
|
|
grid(
|
|
|
|
gutter: 1em,
|
|
|
|
columns: (5.5cm, 0.75fr, 7fr),
|
|
|
|
[], [], content
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}, styles)
|
|
|
|
|
2023-11-27 15:40:19 +01:00
|
|
|
let offset = measure(left, styles)
|
2023-11-30 15:11:59 +01:00
|
|
|
|
2023-11-27 15:40:19 +01:00
|
|
|
grid(
|
|
|
|
gutter: 1em,
|
|
|
|
columns: (5.5cm, 0.75fr, 7fr),
|
|
|
|
[],
|
2024-01-11 15:31:17 +01:00
|
|
|
if not disable_line {
|
|
|
|
align(center, [
|
|
|
|
#left
|
|
|
|
#v(-0.5em)
|
|
|
|
#line(angle: 90deg, length: size.height - offset.height - 0.5em)
|
|
|
|
])
|
|
|
|
} else {
|
|
|
|
left
|
|
|
|
},
|
2023-11-27 15:40:19 +01:00
|
|
|
content
|
|
|
|
)
|
|
|
|
v(-4pt)
|
2023-11-30 15:11:59 +01:00
|
|
|
})
|
|
|
|
)
|
2023-11-27 15:40:19 +01:00
|
|
|
}
|
|
|
|
|
2023-11-27 16:04:11 +01:00
|
|
|
// A score box between 1 and 5.
|
2023-11-27 15:40:19 +01:00
|
|
|
#let score(level: int) = {
|
|
|
|
|
|
|
|
let elems = ()
|
|
|
|
|
|
|
|
for x in range(5) {
|
|
|
|
if level > x {
|
2023-11-30 15:11:59 +01:00
|
|
|
elems.push(rect(width: 0.4cm, height: 0.2cm, fill: color))
|
2023-11-27 15:40:19 +01:00
|
|
|
} else {
|
2023-11-30 15:11:59 +01:00
|
|
|
elems.push(rect(width: 0.4cm, height: 0.2cm, fill: color.lighten(60%)))
|
2023-11-27 15:40:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
v(0.1cm)
|
|
|
|
stack(
|
|
|
|
dir: ltr,
|
|
|
|
elems.at(0), h(0.1cm),
|
|
|
|
elems.at(1), h(0.1cm),
|
|
|
|
elems.at(2), h(0.1cm),
|
|
|
|
elems.at(3), h(0.1cm),
|
|
|
|
elems.at(4),
|
|
|
|
)
|
|
|
|
}
|