// This theme is adapted from https://github.com/touying-typ/touying/blob/main/themes/simple.typ by OrangeX4 #import "@preview/touying:0.6.1": * /// Default slide function for the presentation. /// /// - config (dictionary): The configuration of the slide. You can use `config-xxx` to set the configuration of the slide. For more several configurations, you can use `utils.merge-dicts` to merge them. /// /// - repeat (int, auto): The number of subslides. Default is `auto`, which means touying will automatically calculate the number of subslides. /// //// The `repeat` argument is necessary when you use `#slide(repeat: 3, self => [ .. ])` style code to create a slide. The callback-style `uncover` and `only` cannot be detected by touying automatically. /// /// - setting (function): The setting of the slide. You can use it to add some set/show rules for the slide. /// /// - composer (function): The composer of the slide. You can use it to set the layout of the slide. /// /// For example, `#slide(composer: (1fr, 2fr, 1fr))[A][B][C]` to split the slide into three parts. The first and the last parts will take 1/4 of the slide, and the second part will take 1/2 of the slide. /// /// If you pass a non-function value like `(1fr, 2fr, 1fr)`, it will be assumed to be the first argument of the `components.side-by-side` function. /// /// The `components.side-by-side` function is a simple wrapper of the `grid` function. It means you can use the `grid.cell(colspan: 2, ..)` to make the cell take 2 columns. /// /// For example, `#slide(composer: 2)[A][B][#grid.cell(colspan: 2)[Footer]]` will make the `Footer` cell take 2 columns. /// /// If you want to customize the composer, you can pass a function to the `composer` argument. The function should receive the contents of the slide and return the content of the slide, like `#slide(composer: grid.with(columns: 2))[A][B]`. /// /// - bodies (array): The contents of the slide. You can call the `slide` function with syntax like `#slide[A][B][C]` to create a slide. #let slide( config: (:), repeat: auto, setting: body => body, composer: auto, ..bodies, ) = touying-slide-wrapper(self => { let header(self) = utils.call-or-display(self, self.store.header) let footer(self) = { text(size: 0.5em, fill: self.colors.neutral-lightest, grid( align: (left + horizon, center + horizon, right + horizon), fill: self.colors.secondary, columns: (1fr, 4.5fr, 1fr), // gutter: 0em, // stroke: (x: self.colors.secondary + 0.5em), rows: 100%, box(inset: (left: self.page.margin.x / 2), utils.call-or-display(self, self.store.footer-left)), utils.call-or-display(self, self.store.footer), box(fill: self.colors.primary, height: 100%, inset: (x: self.page.margin.x / 2), align(center, utils.call-or-display(self, self.store.footer-right))), ) ) } let self = utils.merge-dicts( self, config-page( header: header, footer: footer, ), config-common(subslide-preamble: self.store.subslide-preamble), ) touying-slide(self: self, config: config, repeat: repeat, setting: setting, composer: composer, ..bodies) }) /// Centered slide for the presentation. /// /// - config (dictionary): The configuration of the slide. You can use `config-xxx` to set the configuration of the slide. For several configurations, you can use `utils.merge-dicts` to merge them. #let centered-slide(config: (:), ..args) = touying-slide-wrapper(self => { touying-slide(self: self, ..args.named(), config: config, align(center + horizon, args.pos().sum(default: none))) }) /// Title slide for the presentation. /// /// Example: `#title-slide(title-image: "assets/title-image.png")` /// /// - content (content | none): The content of the title slide, typically an image. The content will be displayed centered above the title and subtitle. /// /// - config (dictionary): The configuration of the slide. You can use `config-xxx` to set the configuration of the slide. For several configurations, you can use `utils.merge-dicts` to merge them. #let title-slide(content, config: (:), ..args) = touying-slide-wrapper(self => { let body = { set block(spacing: 0em) // show text: it => align(right + horizon, it) set text(fill: self.colors.neutral-lightest) block( inset: (x: self.page.margin.x * 2/3, y: 0.5cm), width: 100%, height: 1fr, content ) block( fill: self.colors.primary, width: 100%, height: 2.2cm, inset: (x: self.page.margin.x * 2/3), align(right + horizon, text(size: 1.4em, weight: "bold", self.info.title)) ) let secondary-info = (self.info.subtitle, self.info.author, self.info.date.display("[month repr:long] [day], [year]")).filter(it => it != none).join(" | ") block( fill: self.colors.secondary, width: 100%, height: 1.1cm, inset: (x: self.page.margin.x * 2/3), align(right + horizon, text(size: 0.9em, secondary-info)) ) block( width: 100%, height: 2.2cm, inset: (x: self.page.margin.x * 2/3, y: 0.35cm), box(image(self.info.institute-logo, height: 1fr)) + h(1fr) + box(image(self.info.university-logo, height: 1fr)) ) } let self = utils.merge-dicts( self, config-common(freeze-slide-counter: true), config-page(margin: 0em) ) touying-slide(self: self, ..args.named(), config: config, body) }) /// New section slide for the presentation. You can update it by updating the `new-section-slide-fn` argument for `config-common` function. /// /// - config (dictionary): The configuration of the slide. You can use `config-xxx` to set the configuration of the slide. For more several configurations, you can use `utils.merge-dicts` to merge them. #let new-section-slide(config: (:), body) = centered-slide(config: config, [ #text(1.2em, weight: "bold", utils.display-current-heading(level: 1)) #body ]) /// Focus on some content. /// /// Example: `#focus-slide[Wake up!]` /// /// - config (dictionary): The configuration of the slide. You can use `config-xxx` to set the configuration of the slide. For more several configurations, you can use `utils.merge-dicts` to merge them. /// /// - background (color, auto): The background color of the slide. Default is `auto`, which means the primary color of the slides. /// /// - foreground (color): The foreground color of the slide. Default is `white`. #let focus-slide(config: (:), background: auto, foreground: white, body) = touying-slide-wrapper(self => { self = utils.merge-dicts( self, config-common(freeze-slide-counter: true), config-page(fill: if background == auto { self.colors.primary } else { background }), ) set text(fill: foreground, size: 1.5em) touying-slide(self: self, config: config, align(center + horizon, body)) }) /// Fancy Ulm University theme (Institute of Software Engineering and Programming Languages). /// /// Example: /// /// ```typst /// #show: fancyuulm.with(aspect-ratio: "16-9", config-colors(primary: blue))` /// ``` /// /// The default colors: /// /// ```typst /// config-colors( /// neutral-light: gray, /// neutral-lightest: rgb("#ffffff"), /// neutral-darkest: rgb("#000000"), /// primary: rgb("#A32638"), /// secondary: rgb("#A9A28D"), /// ) /// ``` /// /// - aspect-ratio (string): The aspect ratio of the slides. Default is `16-9`. /// /// - header (function): The header of the slides. Default is `self => utils.display-current-heading(setting: utils.fit-to-width.with(grow: false, 100%), depth: self.slide-level)`. /// /// - footer-left (function): The left part of the footer. Default is `self => self.info.author`. /// /// - footer (function): The footer of the slides. Default is `self => self.info.title`. /// /// - footer-right (content): The right part of the footer. Default is `context utils.slide-counter.display()`. /// /// - primary (color): The primary color of the slides. Default is `rgb("#A32638")`. /// /// - secondary (color): The secondary color of the slides. Default is `rgb("#A9A28D")`. /// /// - subslide-preamble (content): The preamble of the subslides. Default is `block(below: 1.5em, text(1.2em, weight: "bold", utils.display-current-heading(level: 2)))`. /// /// - include-new-section-slides (bool): Whether to include slides for introducing new sections. Default is `false`. #let fancyuulm( aspect-ratio: "16-9", header: self => [],//utils.display-current-heading( // setting: utils.fit-to-width.with(grow: false, 100%), // level: 1, // depth: self.slide-level, // ), footer-left: self => self.info.author, footer: self => [#self.info.title -- #self.info.subtitle -- #utils.display-current-heading(level: 1)], footer-right: context utils.slide-counter.display(), primary: rgb("#A32638"), secondary: rgb("#A9A28D"), subslide-preamble: block( below: 1.3cm, text(1.5em, weight: "bold", utils.display-current-heading(level: 2)), ), include-new-section-slides: false, ..args, body, ) = { show: touying-slides.with( config-page( paper: "presentation-" + aspect-ratio, margin: (x: 2cm, top: 1.5cm, bottom: 2cm), footer-descent: 1.2cm, ), config-common( slide-fn: slide, new-section-slide-fn: if include-new-section-slides { new-section-slide }, zero-margin-header: false, zero-margin-footer: true, ), config-methods( init: (self: none, body) => { set text(size: 18pt, number-width: "tabular", font: "Fira Sans") show raw: set text(font: "Fira Code") show math.equation: set text(font: "Noto Sans Math") set par(spacing: 1cm) set footnote.entry(indent: 0cm, clearance: 0.3cm) show footnote.entry: set text(size: 8pt) show footnote.entry: set cite(form: "full") show footnote.entry: box.with(width: 62.5%) // set list(spacing: 1cm) // show list: it => { // show list: set list(spacing: 0.75cm) // it // } // show raw.where(block: false): box // show raw.where(block: false): set box( // fill: self.colors.neutral-lighter, // inset: (x: 5pt, y: 0pt), // outset: (y: 5pt), // radius: 3pt, // ) // set table(inset: 9pt, stroke: (0.5pt + self.colors.neutral-light)) // show table: table => { // show raw.where(block: false): set box( // fill: none, // inset: (x: 1pt), // outset: 0pt // ) // table // } body }, alert: utils.alert-with-primary-color, ), config-colors( neutral-light: luma(200), neutral-lighter: luma(250), neutral-lightest: rgb("#ffffff"), neutral-darkest: rgb("#000000"), primary: primary, secondary: secondary, ), // Save the variables for later use config-store( header: header, footer-left: footer-left, footer: footer, footer-right: footer-right, subslide-preamble: subslide-preamble, ), ..args, ) body }