#import "@preview/hydra:0.6.1": hydra #import "cover.typ": cover #import "abstracts.typ": abstracts #import "todos.typ": todos, show-todos #import "etablissements.typ": * #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: "UR", 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 ) = { assert-etablissements(university) 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( university: university, 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, ) }