Add typst letter template
This commit is contained in:
parent
481c1d69d5
commit
eba88bcc4b
23
typst/letter/example.typ
Normal file
23
typst/letter/example.typ
Normal file
@ -0,0 +1,23 @@
|
||||
#import "letter.typ": template
|
||||
|
||||
#show: template.with(
|
||||
lang: "en",
|
||||
name: "Joël von der Weid",
|
||||
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",
|
||||
to-details: [
|
||||
Adaptyv Bio \
|
||||
Biopole Life Science Campus \
|
||||
Route de la Corniche 5 \
|
||||
1066 Epalinges
|
||||
],
|
||||
)
|
||||
|
||||
Dear Sir or Madam,
|
||||
|
||||
#lorem(50)
|
||||
|
||||
Sincerely,
|
||||
|
||||
Joël von der Weid
|
||||
101
typst/letter/letter.typ
Normal file
101
typst/letter/letter.typ
Normal file
@ -0,0 +1,101 @@
|
||||
#let line-stroke = (paint: rgb("#731010"), thickness: 1pt, cap: "round")
|
||||
|
||||
#let template(
|
||||
lang: "fr",
|
||||
background: rgb("fff"),
|
||||
name: "Joël von der Weid",
|
||||
from-address: "Rue de la Baumettaz 7, CH-1023 Crissier",
|
||||
from-email: "jvonderweid@ikmail.com",
|
||||
from-phone: "+41 79 861 88 08",
|
||||
to-details: none,
|
||||
subject: none,
|
||||
date: none,
|
||||
margin: (x: 2.5cm, y: 2cm),
|
||||
vertical-center-level: 2,
|
||||
doc
|
||||
) = {
|
||||
set page(fill: background, margin: margin)
|
||||
set text(font: ("Libertinus Serif"))
|
||||
|
||||
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 body = [
|
||||
#set text(size: 11pt, weight: "medium")
|
||||
#show par: set par(spacing: 1.75em, justify: true)
|
||||
#subject
|
||||
#doc
|
||||
]
|
||||
|
||||
let header = {
|
||||
set text(font: "Nimbus Sans", style: "italic")
|
||||
set par(leading: 0.9em)
|
||||
grid(
|
||||
inset: (x: 0cm, y: 3mm),
|
||||
columns: (50%, 1fr),
|
||||
grid.hline(start: 1, stroke: line-stroke),
|
||||
[
|
||||
#text(size: 25pt, weight: "bold", name) \
|
||||
#text(size: 10pt, fill: rgb("444"), from-address)
|
||||
],
|
||||
align(bottom + end, box(
|
||||
inset: (top: 1em),
|
||||
[
|
||||
#set par(leading: 0.7em)
|
||||
#set text(size: 10pt, fill: rgb("444"))
|
||||
#from-phone \
|
||||
#from-email
|
||||
]
|
||||
)),
|
||||
grid.hline(end: 1, stroke: line-stroke),
|
||||
)
|
||||
v(2cm)
|
||||
set par(leading: 0.6em)
|
||||
set text(style: "normal")
|
||||
[
|
||||
#h(10cm)
|
||||
#box(width: 100% - 10cm, [
|
||||
#text(size: 10pt, to-details)
|
||||
#v(1.5cm)
|
||||
#if date != none {
|
||||
date
|
||||
}
|
||||
])
|
||||
]
|
||||
v(1cm)
|
||||
}
|
||||
|
||||
layout(size => context [
|
||||
#let header-sz = measure(block(width: size.width, header))
|
||||
#let body-sz = measure(block(width: size.width, body))
|
||||
|
||||
#let ratio = (header-sz.height + body-sz.height) / size.height
|
||||
#let overflowing = ratio > 1
|
||||
|
||||
#if overflowing or vertical-center-level == none {
|
||||
header
|
||||
subject
|
||||
body
|
||||
} else {
|
||||
// If no overflow of the first page, we do a bit of centering magic for style
|
||||
|
||||
grid(
|
||||
rows: (auto, 1fr),
|
||||
header,
|
||||
box([
|
||||
#v(1fr * ratio)
|
||||
#body
|
||||
#v(vertical-center-level * 1fr)
|
||||
]),
|
||||
)
|
||||
}
|
||||
])
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user