|  | 
|  | 1 | + | 
|  | 2 | +/// "Simpres" theme by thy0s | 
|  | 3 | +/// Inspired by and partially taken from: | 
|  | 4 | +/// - https://github.com/touying-typ/touying/blob/main/themes/university.typ | 
|  | 5 | +/// - https://github.com/touying-typ/touying/blob/main/themes/metropolis.typ | 
|  | 6 | +/// - https://github.com/JoshuaLampert/clean-math-presentation | 
|  | 7 | + | 
|  | 8 | +#import "@preview/touying:0.6.1": * | 
|  | 9 | + | 
|  | 10 | +/// Standard content "slide": | 
|  | 11 | +/// - "title" (string) sets the title if function is called directly. | 
|  | 12 | +/// - "footer" (string) allows for overriding the default footer for the presentation. | 
|  | 13 | +/// - "show-level-one" (bool) allows for toggling the level 1 heading of an individual slide. | 
|  | 14 | +#let slide( | 
|  | 15 | +  title: auto, | 
|  | 16 | +  footer: auto, | 
|  | 17 | +  show-level-one: none, | 
|  | 18 | +  ..args, | 
|  | 19 | +) = touying-slide-wrapper(self => { | 
|  | 20 | +  if title != auto { | 
|  | 21 | +    self.store.title = title | 
|  | 22 | +  } | 
|  | 23 | +  if footer != auto { | 
|  | 24 | +    self.store.footer = footer | 
|  | 25 | +  } | 
|  | 26 | +  let header(self) = { | 
|  | 27 | +    set align(top) | 
|  | 28 | +    show: components.cell.with(fill: self.colors.primary, inset: 1em) | 
|  | 29 | +    set align(horizon) | 
|  | 30 | +    set text(fill: self.colors.neutral-lightest, size: .7em) | 
|  | 31 | + | 
|  | 32 | +    if show-level-one == true or self.store.show-level-one and show-level-one != false { | 
|  | 33 | +      utils.display-current-heading(level: 1) | 
|  | 34 | +      linebreak() | 
|  | 35 | +    } | 
|  | 36 | + | 
|  | 37 | +    set text(size: 1.8em, weight: "bold") | 
|  | 38 | +    if self.store.title != none { | 
|  | 39 | +      utils.call-or-display(self, self.store.title) | 
|  | 40 | +    } else { | 
|  | 41 | +      utils.display-current-heading(level: 2) | 
|  | 42 | +    } | 
|  | 43 | +  } | 
|  | 44 | +  let footer(self) = { | 
|  | 45 | +    set align(bottom) | 
|  | 46 | +    show: pad.with(.4em) | 
|  | 47 | +    set text(fill: self.colors.neutral-darkest, size: .7em) | 
|  | 48 | +    utils.call-or-display(self, self.store.footer) | 
|  | 49 | +    h(1fr) | 
|  | 50 | +    context utils.slide-counter.display() + " / " + utils.last-slide-number | 
|  | 51 | +  } | 
|  | 52 | +  self = utils.merge-dicts( | 
|  | 53 | +    self, | 
|  | 54 | +    config-page( | 
|  | 55 | +      header: header, | 
|  | 56 | +      footer: footer, | 
|  | 57 | +    ), | 
|  | 58 | +  ) | 
|  | 59 | +  touying-slide(self: self, ..args) | 
|  | 60 | +}) | 
|  | 61 | + | 
|  | 62 | +/// "title-slide": | 
|  | 63 | +/// - Title, subtitle, presenter, institution and date are taken directly from the "config-info" | 
|  | 64 | +#let title-slide( | 
|  | 65 | +  config: (:), | 
|  | 66 | +  extra: none, | 
|  | 67 | +  ..args, | 
|  | 68 | +) = touying-slide-wrapper(self => { | 
|  | 69 | +  self = utils.merge-dicts( | 
|  | 70 | +    self, | 
|  | 71 | +    config, | 
|  | 72 | +    config-common(freeze-slide-counter: true), | 
|  | 73 | +    config-page(fill: self.colors.neutral-lightest), | 
|  | 74 | +  ) | 
|  | 75 | +  let info = self.info + args.named() | 
|  | 76 | +  let body = { | 
|  | 77 | +    set text(fill: self.colors.neutral-darkest) | 
|  | 78 | +    set std.align(horizon) | 
|  | 79 | +    block( | 
|  | 80 | +      width: 100%, | 
|  | 81 | +      inset: 2em, | 
|  | 82 | +      { | 
|  | 83 | +        text(size: 1.5em, text(weight: "bold", fill: self.colors.primary, info.title)) | 
|  | 84 | +        if info.subtitle != none { | 
|  | 85 | +          linebreak() | 
|  | 86 | +          block(spacing: 1em, text(weight: "medium", info.subtitle)) | 
|  | 87 | +        } | 
|  | 88 | +        line(length: 100%, stroke: 2pt + self.colors.primary) | 
|  | 89 | +        set text(size: .9em) | 
|  | 90 | +        if info.author != none { | 
|  | 91 | +          block(spacing: 1em, info.author) | 
|  | 92 | +        } | 
|  | 93 | +        if info.institution != none { | 
|  | 94 | +          block(spacing: 1em, info.institution) | 
|  | 95 | +        } | 
|  | 96 | +        if info.date != none { | 
|  | 97 | +          block(spacing: 1em, info.date.display("[year]-[month]-[day]")) | 
|  | 98 | +        } | 
|  | 99 | +        if extra != none { | 
|  | 100 | +          block(spacing: 1em, extra) | 
|  | 101 | +        } | 
|  | 102 | +      }, | 
|  | 103 | +    ) | 
|  | 104 | +  } | 
|  | 105 | +  touying-slide(self: self, body) | 
|  | 106 | +}) | 
|  | 107 | + | 
|  | 108 | +///"outline-slide" based on the standard slide: | 
|  | 109 | +/// - depth: Describes the max heading level displayed in the outline | 
|  | 110 | +/// - title: Modify the title of the outline slide (e.g. for different languages) | 
|  | 111 | +#let outline-slide( | 
|  | 112 | +  depth: 2, | 
|  | 113 | +  title: "Outline", | 
|  | 114 | +) = slide( | 
|  | 115 | +  title: title, | 
|  | 116 | +  show-level-one: false, | 
|  | 117 | +)[ | 
|  | 118 | +  #show outline.entry.where(level: 1): it => strong(it) | 
|  | 119 | +  #components.adaptive-columns( | 
|  | 120 | +    outline( | 
|  | 121 | +      title: none, | 
|  | 122 | +      indent: auto, | 
|  | 123 | +      depth: depth, | 
|  | 124 | +    ), | 
|  | 125 | +  ) | 
|  | 126 | +] | 
|  | 127 | + | 
|  | 128 | +/// "new-section-slide" is shown for every level one heading (i.e. section headings): | 
|  | 129 | +/// - numbered: Display the heading number if it exists (default: true) | 
|  | 130 | +#let new-section-slide( | 
|  | 131 | +  config: (:), | 
|  | 132 | +  numbered: true, | 
|  | 133 | +  body, | 
|  | 134 | +) = touying-slide-wrapper(self => { | 
|  | 135 | +  let slide-body = { | 
|  | 136 | +    set std.align(horizon) | 
|  | 137 | +    show: pad.with(20%) | 
|  | 138 | +    set text(size: 1.8em, fill: self.colors.primary, weight: "bold") | 
|  | 139 | +    stack( | 
|  | 140 | +      dir: ttb, | 
|  | 141 | +      spacing: .65em, | 
|  | 142 | +      utils.display-current-heading(level: 1, numbered: numbered), | 
|  | 143 | +      block( | 
|  | 144 | +        height: 2pt, | 
|  | 145 | +        width: 100%, | 
|  | 146 | +        spacing: 0pt, | 
|  | 147 | +        components.progress-bar(height: 2pt, self.colors.primary, self.colors.secondary), | 
|  | 148 | +      ), | 
|  | 149 | +    ) | 
|  | 150 | +    body | 
|  | 151 | +  } | 
|  | 152 | +  touying-slide(self: self, config: config, slide-body) | 
|  | 153 | +}) | 
|  | 154 | + | 
|  | 155 | +#let focus-slide(body) = touying-slide-wrapper(self => { | 
|  | 156 | +  self = utils.merge-dicts( | 
|  | 157 | +    self, | 
|  | 158 | +    config-page( | 
|  | 159 | +      fill: self.colors.primary, | 
|  | 160 | +      margin: 2em, | 
|  | 161 | +    ), | 
|  | 162 | +  ) | 
|  | 163 | +  set text(fill: self.colors.neutral-lightest, size: 2em) | 
|  | 164 | +  touying-slide(self: self, align(horizon + center, body)) | 
|  | 165 | +}) | 
|  | 166 | + | 
|  | 167 | + | 
|  | 168 | +/// "touying-criterion": | 
|  | 169 | +/// - "aspect-ratio" - Set the format of the slides (default: 16-9), (alternatively 4-3) | 
|  | 170 | +/// - "lang" (ISO 639-1/2/3 language code) - Set the language of the presentation (default: "en") | 
|  | 171 | +/// - "font" - Set the font of your choosing (default: Source Sans 3) Available at: https://api.fontsource.org/v1/download/source-sans-3 | 
|  | 172 | +/// - "text-size" - Set font size for the text body (default: 22pt) | 
|  | 173 | +/// - "show-level-one" (bool) - Show the section heading on the contents slides (defualt: true) | 
|  | 174 | +/// - "footer" - Set the default footer for content slides (can be overridden for individual slides) | 
|  | 175 | +#let touying-simpres( | 
|  | 176 | +  aspect-ratio: "16-9", | 
|  | 177 | +  lang: "en", | 
|  | 178 | +  font: "Source Sans 3", | 
|  | 179 | +  text-size: 22pt, | 
|  | 180 | +  show-level-one: true, | 
|  | 181 | +  footer: none, | 
|  | 182 | +  ..args, | 
|  | 183 | +  body, | 
|  | 184 | +) = { | 
|  | 185 | +  set text(size: text-size, font: font, lang: lang) | 
|  | 186 | +  show: touying-slides.with( | 
|  | 187 | +    config-page( | 
|  | 188 | +      paper: "presentation-" + aspect-ratio, | 
|  | 189 | +      margin: (top: 3.5em, bottom: 1.5em, x: 2em), | 
|  | 190 | +    ), | 
|  | 191 | +    config-common( | 
|  | 192 | +      slide-fn: slide, | 
|  | 193 | +      new-section-slide-fn: new-section-slide, | 
|  | 194 | +    ), | 
|  | 195 | +    config-methods(alert: (self: none, it) => text(fill: self.colors.primary, it)), | 
|  | 196 | +    config-colors( | 
|  | 197 | +      primary: rgb("003366"), | 
|  | 198 | +      secondary: rgb("CCE5FF"), | 
|  | 199 | +      neutral-lightest: rgb("FFFFFF"), | 
|  | 200 | +      neutral-darkest: rgb("000000"), | 
|  | 201 | +    ), | 
|  | 202 | +    config-store( | 
|  | 203 | +      title: none, | 
|  | 204 | +      footer: footer, | 
|  | 205 | +      show-level-one: show-level-one, | 
|  | 206 | +    ), | 
|  | 207 | +    ..args, | 
|  | 208 | +  ) | 
|  | 209 | +  body | 
|  | 210 | +} | 
0 commit comments