template-thesis-matisse/lib/matisse-thesis.typ
Jean-Marie Mineau 1b5d007289
wip
2025-06-12 11:51:21 +02:00

225 lines
5.5 KiB
Typst

#import "@preview/hydra:0.6.1": hydra
#import "cover.typ": cover
#import "abstracts.typ": abstracts
#import "todos.typ": todos, show-todos
#let matisse-thesis(
// English title, will be used for the document title metadata
title-en: "",
title-fr: "",
author: "",
affiliation: "",
defense-place: "",
defense-date: "",
jury-content: [],
university: [l'Université de Rennes],
speciality: "Informatique",
// List of keyword for the abstract
keywords-en: (),
// List of french keywords for the abstract
keywords-fr: (),
abstract-en: [],
abstract-fr: [],
// If the current document is a draft
draft: true,
bibliography-style: "association-for-computing-machinery",
// text font
font: "New Computer Modern",
// font for heading
heading-font: "TeX Gyre Heros",
// text lang
lang: "en",
school-color-verso: rgb("0054a0"),
body
) = {
if draft {
todos()
} else {
show-todos.update(false)
}
// ---------- GENERAL ----------
let draft-string = ""
if draft { draft-string = "DRAFT - " }
set document(
title: draft-string + title-en,
author: author,
)
set par(justify: true)
set text(font: font, fill: black, lang: lang)
// ---------- PAGE FORMAT ---------- //
set page("a4",
margin: (outside: 20mm, inside: 30mm, top: 50mm, bottom: 50mm),
numbering: "1",
number-align: center,
header: context {
// disable linebreaks in header
show linebreak: none
// get the current page number
let current-page = here().page()
let all-lvl1 = query(heading.where(level: 1))
if all-lvl1.any(it => it.location().page() == current-page) {
return
}
// if the page is odd
if calc.odd(current-page) {
// display the last level-1 heading
let header-content = hydra(1,
display: (_, it) => {
if it.numbering != none {
let nb = counter(heading).at(it.location())
let nb-fmt = numbering(it.numbering, ..nb)
[#it.supplement #nb-fmt -- _ #it.body _ ]
} else { emph(it.body) }
}
)
text(0.35cm, header-content)
}
// if the page is even
else {
// display last level-2 heading (current page included)
let header-content = hydra(2, use-last: true,
display: (_, it) => {
if it.numbering == none [_ #it.body _ ]
else {
let nb = counter(heading).at(it.location())
let nb-fmt = numbering(
it.numbering.replace(" ", "."),
..nb
)
[ _ #nb-fmt #it.body _ ]
}
}
)
align(right, text(0.35cm, header-content))
}
// horizontal rule
v(-.3cm)
line(length: 100%, stroke: .2mm)
}
)
// ---------- HEADINGS ----------
// for the thesis' body:
// 1. headings are normally numbered
// (there is a small space after the last number)
set heading(numbering: "1.1 ")
// 2. level-1 headings are called chapters
show heading.where(level: 1): set heading(supplement: [Chapter])
// for level-1 headings
show heading.where(level: 1): it => context {
// always start on odd pages
pagebreak(to: "odd")
set align(right)
v(-.8cm)
// if numbering is enabled, display level-1 heading number
if it.numbering != none {
let sec-nb = counter(heading).get().first()
let fmt-nb = numbering(heading.numbering, sec-nb)
text(
smallcaps[#heading.supplement #fmt-nb \ ],
size: .45cm, weight: "regular", font: font,
)
v(0cm)
}
// level-1 heading name
text(smallcaps(it.body), font: heading-font, size: .9cm)
set align(left)
// horizontal rule
v(.7cm)
line(length: 100%, stroke: .2mm)
v(.7cm)
}
// ---------- FIGURES ----------
show figure.caption: it => box(
inset: (left: 1em, right: 1em),
align(left, it)
)
// ---------- OUTLINES ----------
// justify outline entries
show outline.entry: set par(justify: true)
show outline: out => {
show outline.entry.where(level: 1): ent => {
// for the table of contents
if out.target == selector(heading) {
block(above: 1.2em)[#ent]
}
// for other types of outlines
else {
link(
ent.element.location(),
[#ent.prefix(): #h(.5em) #ent.inner()]
)
}
}
out
}
// disable linebreaks in outlines
show outline.entry: it => {
show linebreak: none
it
}
// ---------- FOOTNOTES ----------
show footnote.entry: it => {
let loc = it.note.location()
numbering(
"1. ",
..counter(footnote).at(loc),
)
it.note.body
}
// ---------- BIBLIOGRAPHY ----------
set bibliography(style: bibliography-style)
// ---------- COVER PAGE ----------
cover(
title-en: title-en,
title-fr: title-fr,
author: author,
affiliation: affiliation,
defense-place: defense-place,
defense-date: defense-date,
jury-content: jury-content,
university: university,
speciality: speciality,
heading-font: heading-font,
)
// ---------- BODY ----------
set par.line(numbering: n => text(red)[#n]) if draft
show figure: set par.line(numbering: none) if draft
body
// ---------- ABSTRACT ----------
abstracts(
title-fr: title-fr, keywords-fr: keywords-fr, abstract-fr: abstract-fr,
title-en: title-en, keywords-en: keywords-en, abstract-en: abstract-en,
heading-font: heading-font, school-color-verso: school-color-verso,
)
}