Improve letter typst template

This commit is contained in:
Joël von der Weid 2025-03-19 17:06:54 +01:00
parent eba88bcc4b
commit 4a26c6980b
2 changed files with 76 additions and 32 deletions

View File

@ -4,7 +4,6 @@
lang: "en", lang: "en",
name: "Joël von der Weid", name: "Joël von der Weid",
subject: "Cover letter for the Software Engineer (Backend) position", subject: "Cover letter for the Software Engineer (Backend) position",
date: "Sézegnin, 16 March 2025",
from-address: "Route de Sézegnin 63, CH-1285 Sézegnin", from-address: "Route de Sézegnin 63, CH-1285 Sézegnin",
to-details: [ to-details: [
Adaptyv Bio \ Adaptyv Bio \

View File

@ -1,4 +1,9 @@
#let line-stroke = (paint: rgb("#731010"), thickness: 1pt, cap: "round") #let line-stroke = (paint: rgb("#731010"), thickness: 1pt, cap: "round")
#let header-font = ("Nimbus Sans", "Nimbus Sans L")
#let body-font = ("Libertinus Serif")
#let months-en = ("", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December")
#let months-fr = ("", "janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre")
#let template( #let template(
lang: "fr", lang: "fr",
@ -9,41 +14,44 @@
from-phone: "+41 79 861 88 08", from-phone: "+41 79 861 88 08",
to-details: none, to-details: none,
subject: none, subject: none,
date: none, place: "Crissier",
margin: (x: 2.5cm, y: 2cm), date: datetime.today(),
margin: (top: 1.5cm, left: 2.5cm, right: 2.5cm, bottom: 2cm),
font-size: 11pt,
vertical-center-level: 2, vertical-center-level: 2,
appendices: (),
doc doc
) = { ) = {
set page(fill: background, margin: margin) set page(fill: background, margin: margin, paper: "a4", footer: context {
set text(font: ("Libertinus Serif")) if counter(page).final().first() > 1 [
#align(right, counter(page).display("1/1", both: true))
let subject = if subject != none {
let head = if lang == "en" { "Subject" } else { "Concerne " }
[
#text(weight: "bold", underline(head) + ": " + subject)
#v(0.5cm)
] ]
} else { })
none
let full-date = {
let date = if date != none {
let months = if lang == "en" { months-en } else { months-fr }
str(date.day()) + " " + months.at(date.month()) + " " + str(date.year())
}
if place == none {
date
} else if date == none {
place
} else {
let sep = if lang == "en" { ", " } else { ", le " }
place + sep + date
}
} }
let body = [
#set text(size: 11pt, weight: "medium")
#show par: set par(spacing: 1.75em, justify: true)
#subject
#doc
]
let header = { let header = {
set text(font: "Nimbus Sans", style: "italic") set text(font: header-font, style: "italic")
set par(leading: 0.9em) set par(leading: 0.8em)
grid( grid(
inset: (x: 0cm, y: 3mm), inset: (x: 0cm, y: 2.5mm),
columns: (50%, 1fr), columns: (50%, 1fr),
grid.hline(start: 1, stroke: line-stroke), grid.hline(start: 1, stroke: line-stroke),
[ [
#text(size: 25pt, weight: "bold", name) \ #text(size: 22pt, weight: "bold", name) \
#text(size: 10pt, fill: rgb("444"), from-address) #text(size: 10pt, fill: rgb("444"), from-address)
], ],
align(bottom + end, box( align(bottom + end, box(
@ -57,22 +65,61 @@
)), )),
grid.hline(end: 1, stroke: line-stroke), grid.hline(end: 1, stroke: line-stroke),
) )
v(2cm) v(1cm)
set par(leading: 0.6em) set par(leading: 0.6em)
set text(style: "normal") set text(style: "normal")
[ [
#h(10cm) #h(10cm)
#box(width: 100% - 10cm, [ #box(width: 100% - 10cm, [
#text(size: 10pt, to-details) #text(size: 10pt, to-details)
#v(1.5cm) #v(2cm)
#if date != none { #if full-date != none {
date text(size: font-size, font: body-font, full-date)
} }
]) ])
] ]
v(1cm) v(1cm)
} }
let subject = if subject != none {
let head = if lang == "en" { "Subject" } else { "Concerne " }
[
#text(weight: "bold", underline(head) + ": " + subject)
#v(0.5cm)
]
} else {
none
}
let appendices-content = {
if appendices.len() > 0 {
[
#v(0.5cm)
#if lang == "en" { "Appendices: " } else { "Annexes : " }
#context {
box(baseline: 100% - measure("Appendices").height)[
#if type(appendices) == array {
for (i, value) in appendices.enumerate() {
"- " + value + linebreak()
}
} else {
"- " + appendices + linebreak()
}
]
}
]
}
}
let body = [
#set text(font: body-font, size: font-size, weight: "regular")
#show par: set par(spacing: 1.75em, justify: true)
#subject
#doc
#appendices-content
]
layout(size => context [ layout(size => context [
#let header-sz = measure(block(width: size.width, header)) #let header-sz = measure(block(width: size.width, header))
#let body-sz = measure(block(width: size.width, body)) #let body-sz = measure(block(width: size.width, body))
@ -82,17 +129,15 @@
#if overflowing or vertical-center-level == none { #if overflowing or vertical-center-level == none {
header header
subject
body body
} else { } else {
// If no overflow of the first page, we do a bit of centering magic for style // If no overflow of the first page, we do a bit of centering magic for style
grid( grid(
rows: (auto, 1fr), rows: (auto, 1fr),
header, header,
box([ box([
#v(1fr * ratio) #v(1fr * ratio)
#body #body
#v(vertical-center-level * 1fr) #v(vertical-center-level * 1fr)
]), ]),
) )