#import "modules/titlepage.typ": * #import "@preview/glossarium:0.5.9": print-glossary #import "@preview/hydra:0.6.3": hydra #let in-outline = state("in-outline", false) #let flex-caption(long, short) = context { if in-outline.at(here()) { short } else { long } } #let preface( settings: (), preface ) = { // Page Setup set page( margin: ( left: settings.page-margins.left, right: settings.page-margins.right, top: settings.page-margins.top, bottom: settings.page-margins.bottom ), header-ascent: 2%, numbering: "i", number-align: right ) counter(page).update(2) // Body Font Family set text( font: settings.font-body, size: settings.font-body-size, lang: "en" ) show math.equation: set text(weight: 400) // Headings show heading: set block( below: settings.headings-spacing.below, above: settings.headings-spacing.above ) show heading: set text(font: settings.font-heading) show heading.where(level: 1): set text(font: settings.font-heading, size: settings.font-heading-size) set heading(numbering: none) // Paragraphs set par(leading: settings.distance-between-lines, justify: true) // Figures show figure: set text(size: settings.font-figures-subtitle-size) //Indentation of Lists set list(indent: settings.list-indentation) set enum(indent: settings.list-indentation) preface } #let listings( abbreviations: () ) = { // Enable short captions to omit citations show outline: it => { in-outline.update(true) it in-outline.update(false) } // Table of Contents outline( title: { heading(outlined: false, "Table of Contents") }, target: heading.where(supplement: [Chapter], outlined: true), indent: auto, depth: 3 ) v(2.4fr) pagebreak() // List of Figures outline( title: { heading(outlined: false, "List of Figures") }, target: figure.where(kind: image), ) pagebreak() // List of Tables outline( title: { heading(outlined: false, "List of Tables") }, target: figure.where(kind: table) ) pagebreak() // List of Listings outline( title: { heading(outlined: false, "List of Listings") }, target: figure.where(kind: raw) ) pagebreak() // List of Abbreviations heading(outlined: false)[List of Abbreviations] print-glossary( abbreviations, show-all: false, disable-back-references: true, ) } #let main-body( settings: (), body ) = { // Main Body set heading(numbering: settings.headings-numbering-style, supplement: [Chapter]) show heading.where(level: 1): it => { if it.numbering == none { [ #it ] } else { [ #pagebreak() #it ] } counter(figure.where(kind: table)).update(0); counter(figure.where(kind: image)).update(0); counter(figure.where(kind: raw)).update(0); } set figure(numbering: it => { let numbering-of-heading = counter(heading).display(); let top-level-number = numbering-of-heading.slice(0, numbering-of-heading.position(".")) [#top-level-number.#it] }) set page( // Header with current heading header: context { grid(columns: (1fr, 1fr), align(left, emph(hydra(1))), align(right, emph(hydra(2))) ) if hydra(1) != none { line(length: 100%, stroke: 0.5pt, start: (0%, -1.8em)) } }, // Footer with Page Numbering footer: context { let current-page = counter(page).display() let final-page = counter(page).final().first() align(right, current-page) } ) set page( numbering: "1", number-align: center, ) counter(page).update(1) // Set after header and after all initial pages to just apply it to the acutal content set par(spacing: settings.space-before-paragraph, justify: true) // Actual Content body } // Appendix #let appendix(body) = { pagebreak() outline( title: { heading("Appendix", outlined: true, numbering: none) }, target: heading.where(supplement: [Appendix], outlined: true), indent: auto, depth: 3 ) counter(heading).update(0) set heading(numbering: "A.1", supplement: [Appendix]) show heading: it => { let prefixed-numbering; if it.level == 1 and it.numbering != none { prefixed-numbering = [#it.supplement #counter(heading).display()] } else if it.numbering != none { prefixed-numbering = [#counter(heading).display()] } block( below: 0.85em, above: 1.75em )[ #prefixed-numbering #it.body ] } set figure(numbering: it => { let alphabet = ("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z") let numbering-of-heading = counter(heading).display(); let top-level-number = numbering-of-heading.slice(0, numbering-of-heading.position(".")) let index = alphabet.position((el) => { el == top-level-number}) if index == noneĀ { let numberingToAlphabet = numbering("A", int(top-level-number)) [#numberingToAlphabet.#it] } else { [#top-level-number.#it] } }) show heading.where(level: 1): it => { if it.numbering == none { [ #it ] } else { [ #pagebreak() #it ] } counter(figure.where(kind: table)).update(0); counter(figure.where(kind: image)).update(0); counter(figure.where(kind: raw)).update(0); } body } // TODOs #let todo(body) = [ #let rblock = block.with(stroke: red, radius: 0.5em, fill: red.lighten(80%)) #let top-left = place.with(top + left, dx: 1em, dy: -0.35em) #block(inset: (top: 0.35em), { rblock(width: 100%, inset: 1em, body) top-left(rblock(fill: white, outset: 0.25em, text(fill: red)[*TODO*])) }) ] #let outline-todos(title: [TODOS]) = { heading(numbering: none, outlined: false, title) context { let queried-todos = query() let headings = () let last-heading for todo in queried-todos { let new-last-heading = query(selector(heading).before(todo.location())).last() if last-heading != new-last-heading { headings.push((heading: new-last-heading, todos: (todo,))) last-heading = new-last-heading } else { headings.last().todos.push(todo) } } for head in headings { link(head.heading.location())[ #numbering(head.heading.numbering, ..counter(heading).at(head.heading.location())) #head.heading.body ] [ ] box(width: 1fr, repeat[.]) [ ] [#head.heading.location().page()] linebreak() pad(left: 1em, head.todos.map((todo) => { list.item(link(todo.location(), todo.body.children.at(0).body)) }).join()) } } }