first commit
This commit is contained in:
commit
b2ee54ce3c
393
firatheme.typ
Normal file
393
firatheme.typ
Normal file
@ -0,0 +1,393 @@
|
||||
// This theme is inspired by https://github.com/zbowang/BeamerTheme
|
||||
// The typst version was written by https://github.com/OrangeX4
|
||||
|
||||
#import "@preview/touying:0.6.1": *
|
||||
|
||||
#let _typst-builtin-repeat = repeat
|
||||
|
||||
#let fira-header(self) = {
|
||||
if self.store.navigation == "sidebar" {
|
||||
place(
|
||||
right + top,
|
||||
{
|
||||
v(4em)
|
||||
show: block.with(width: self.store.sidebar.width, inset: (x: 1em))
|
||||
set align(left)
|
||||
set par(justify: false)
|
||||
set text(size: .9em)
|
||||
components.custom-progressive-outline(
|
||||
self: self,
|
||||
level: auto,
|
||||
alpha: self.store.alpha,
|
||||
text-fill: (self.colors.primary, self.colors.neutral-darkest),
|
||||
text-size: (1em, .9em),
|
||||
vspace: (-.2em,),
|
||||
indent: (0em, self.store.sidebar.at("indent", default: .5em)),
|
||||
fill: (self.store.sidebar.at("fill", default: _typst-builtin-repeat[.]),),
|
||||
filled: (self.store.sidebar.at("filled", default: false),),
|
||||
paged: (self.store.sidebar.at("paged", default: false),),
|
||||
short-heading: self.store.sidebar.at("short-heading", default: true),
|
||||
)
|
||||
},
|
||||
)
|
||||
} else if self.store.navigation == "mini-slides" {
|
||||
components.mini-slides(
|
||||
self: self,
|
||||
fill: self.colors.primary,
|
||||
alpha: self.store.alpha,
|
||||
display-section: self.store.mini-slides.at("display-section", default: false),
|
||||
display-subsection: self.store.mini-slides.at("display-subsection", default: true),
|
||||
linebreaks: self.store.mini-slides.at("linebreaks", default: true),
|
||||
short-heading: self.store.mini-slides.at("short-heading", default: true),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#let fira-footer(self) = {
|
||||
set align(bottom)
|
||||
set text(size: 0.8em)
|
||||
show: pad.with(.5em)
|
||||
components.left-and-right(
|
||||
text(fill: self.colors.neutral-darkest.lighten(40%), utils.call-or-display(self, self.store.footer)),
|
||||
text(fill: self.colors.neutral-darkest.lighten(20%), utils.call-or-display(self, self.store.footer-right)),
|
||||
)
|
||||
}
|
||||
|
||||
/// 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, array): 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 self = utils.merge-dicts(
|
||||
self,
|
||||
config-page(
|
||||
header: fira-header,
|
||||
footer: none,
|
||||
),
|
||||
config-common(subslide-preamble: self.store.subslide-preamble),
|
||||
)
|
||||
touying-slide(self: self, config: config, repeat: repeat, setting: setting, composer: composer, ..bodies)
|
||||
})
|
||||
|
||||
|
||||
/// Title slide for the presentation. You should update the information in the `config-info` function. You can also pass the information directly to the `title-slide` function.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```typst
|
||||
/// #show: fira-theme.with(
|
||||
/// config-info(
|
||||
/// title: [Title],
|
||||
/// logo: emoji.city,
|
||||
/// ),
|
||||
/// )
|
||||
///
|
||||
/// #title-slide(subtitle: [Subtitle], extra: [Extra information])
|
||||
/// ```
|
||||
///
|
||||
/// - 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.
|
||||
///
|
||||
/// - extra (string, none): The extra information you want to display on the title slide.
|
||||
#let title-slide(
|
||||
config: (:),
|
||||
extra: none,
|
||||
..args,
|
||||
) = touying-slide-wrapper(self => {
|
||||
self = utils.merge-dicts(
|
||||
self,
|
||||
config,
|
||||
config-common(freeze-slide-counter: true),
|
||||
config-page(margin: 0em),
|
||||
)
|
||||
let info = self.info + args.named()
|
||||
let body = {
|
||||
set par(justify: false)
|
||||
set text(fill: self.colors.neutral-darkest)
|
||||
set align(center + horizon)
|
||||
block(
|
||||
width: 100%,
|
||||
inset: 3em,
|
||||
{
|
||||
block(
|
||||
// fill: self.colors.neutral-light,
|
||||
inset: 1em,
|
||||
width: 100%,
|
||||
// radius: 0.2em,
|
||||
text(size: 1.6em, fill: self.colors.primary, text(weight: "bold", info.title, hyphenate: false)) + (
|
||||
if info.subtitle != none {
|
||||
linebreak()
|
||||
text(size: 1.2em, fill: self.colors.primary, info.subtitle)
|
||||
}
|
||||
),
|
||||
)
|
||||
set text(size: 1em)
|
||||
if info.author != none {
|
||||
block(spacing: 1em, info.author)
|
||||
}
|
||||
v(1em)
|
||||
if info.date != none {
|
||||
block(spacing: 1em, utils.display-info-date(self))
|
||||
}
|
||||
set text(size: 1em)
|
||||
if info.institution != none {
|
||||
block(spacing: 1em, info.institution)
|
||||
}
|
||||
if extra != none {
|
||||
block(spacing: 1em, extra)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
touying-slide(self: self, body)
|
||||
})
|
||||
|
||||
|
||||
/// Outline slide 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.
|
||||
///
|
||||
/// - title (string): The title of the slide. Default is `utils.i18n-outline-title`.
|
||||
#let outline-slide(config: (:), title: utils.i18n-outline-title, ..args) = touying-slide-wrapper(self => {
|
||||
self = utils.merge-dicts(
|
||||
self,
|
||||
config-page(
|
||||
footer: none,
|
||||
),
|
||||
)
|
||||
touying-slide(
|
||||
self: self,
|
||||
config: config,
|
||||
components.adaptive-columns(
|
||||
start: underline(text(
|
||||
1.6em,
|
||||
fill: self.colors.primary,
|
||||
weight: "bold",
|
||||
utils.call-or-display(self, title),
|
||||
),stroke: 4pt, offset: 0.2em),
|
||||
text(
|
||||
fill: self.colors.neutral-darkest,
|
||||
outline(title: none, indent: 1em, depth: self.slide-level, ..args),
|
||||
),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
/// New section slide for the presentation. You can update it by updating the `new-section-slide-fn` argument for `config-common` function.
|
||||
///
|
||||
/// Example: `config-common(new-section-slide-fn: new-section-slide.with(numbered: false))`
|
||||
///
|
||||
/// - 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.
|
||||
///
|
||||
/// - title (string): The title of the slide. Default is `utils.i18n-outline-title`.
|
||||
///
|
||||
/// - body (array): The contents of the slide.
|
||||
#let new-section-slide(config: (:), title: utils.i18n-outline-title, ..args, body) = touying-slide-wrapper(self => {
|
||||
self = utils.merge-dicts(
|
||||
self,
|
||||
config-page(
|
||||
footer: none,
|
||||
),
|
||||
)
|
||||
touying-slide(
|
||||
self: self,
|
||||
config: config,
|
||||
components.adaptive-columns(
|
||||
start: text(
|
||||
1.2em,
|
||||
fill: self.colors.primary,
|
||||
weight: "bold",
|
||||
utils.call-or-display(self, title),
|
||||
),
|
||||
text(
|
||||
fill: self.colors.neutral-darkest,
|
||||
components.progressive-outline(
|
||||
alpha: self.store.alpha,
|
||||
title: none,
|
||||
indent: 1em,
|
||||
depth: self.slide-level,
|
||||
..args,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
/// 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.
|
||||
#let focus-slide(config: (:), body) = touying-slide-wrapper(self => {
|
||||
self = utils.merge-dicts(
|
||||
self,
|
||||
config-common(freeze-slide-counter: true),
|
||||
config-page(fill: self.colors.primary, margin: 2em),
|
||||
)
|
||||
set text(fill: self.colors.neutral-lightest, size: 1.5em)
|
||||
touying-slide(self: self, config: config, align(horizon + center, body))
|
||||
})
|
||||
|
||||
|
||||
/// Touying fira theme.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```typst
|
||||
/// #show: fira-theme.with(aspect-ratio: "16-9", config-colors(primary: blue))`
|
||||
/// ```
|
||||
///
|
||||
/// The default colors:
|
||||
///
|
||||
/// ```typ
|
||||
/// config-colors(
|
||||
/// neutral-darkest: rgb("#000000"),
|
||||
/// neutral-dark: rgb("#202020"),
|
||||
/// neutral-light: rgb("#f3f3f3"),
|
||||
/// neutral-lightest: rgb("#ffffff"),
|
||||
/// primary: rgb("#0c4842"),
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// - aspect-ratio (string): The aspect ratio of the slides. Default is `16-9`.
|
||||
///
|
||||
/// - navigation (string): The navigation of the slides. You can choose from `"sidebar"`, `"mini-slides"`, and `none`. Default is `"sidebar"`.
|
||||
///
|
||||
/// - sidebar (dictionary): The configuration of the sidebar. You can set the width, filled, numbered, indent, and short-heading of the sidebar. Default is `(width: 10em, filled: false, numbered: false, indent: .5em, short-heading: true)`.
|
||||
/// - width (string): The width of the sidebar.
|
||||
/// - filled (boolean): Whether the outline in the sidebar is filled.
|
||||
/// - numbered (boolean): Whether the outline in the sidebar is numbered.
|
||||
/// - indent (length): The indent of the outline in the sidebar.
|
||||
/// - short-heading (boolean): Whether the outline in the sidebar is short.
|
||||
///
|
||||
/// - mini-slides (dictionary): The configuration of the mini-slides. You can set the height, x, display-section, display-subsection, and short-heading of the mini-slides. Default is `(height: 4em, x: 2em, display-section: false, display-subsection: true, linebreaks: true, short-heading: true)`.
|
||||
/// - height (length): The height of the mini-slides.
|
||||
/// - x (length): The x position of the mini-slides.
|
||||
/// - display-section (boolean): Whether the slides of sections are displayed in the mini-slides.
|
||||
/// - display-subsection (boolean): Whether the slides of subsections are displayed in the mini-slides.
|
||||
/// - linebreaks (boolean): Whether line breaks are in between links for sections and subsections in the mini-slides.
|
||||
/// - short-heading (boolean): Whether the mini-slides are short. Default is `true`.
|
||||
///
|
||||
/// - footer (content, function): The footer of the slides. Default is `none`.
|
||||
///
|
||||
/// - footer-right (content, function): The right part of the footer. Default is `context utils.slide-counter.display() + " / " + utils.last-slide-number`.
|
||||
///
|
||||
/// - primary (color): The primary color of the slides. Default is `rgb("#0c4842")`.
|
||||
///
|
||||
/// - alpha (fraction, float): The alpha of transparency. Default is `60%`.
|
||||
///
|
||||
/// - outline-title (content, function): The title of the outline. Default is `utils.i18n-outline-title`.
|
||||
///
|
||||
/// - subslide-preamble (content, function): The preamble of the subslide. Default is `self => block(text(1.2em, weight: "bold", fill: self.colors.primary, utils.display-current-heading(depth: self.slide-level)))`.
|
||||
#let fira-theme(
|
||||
aspect-ratio: "4-3",
|
||||
navigation: "sidebar",
|
||||
sidebar: (
|
||||
width: 10em,
|
||||
filled: false,
|
||||
numbered: false,
|
||||
indent: .5em,
|
||||
short-heading: true,
|
||||
),
|
||||
mini-slides: (
|
||||
height: 4em,
|
||||
x: 2em,
|
||||
display-section: false,
|
||||
display-subsection: true,
|
||||
linebreaks: true,
|
||||
short-heading: true,
|
||||
),
|
||||
footer: none,
|
||||
footer-right: context utils.slide-counter.display() + " / " + utils.last-slide-number,
|
||||
primary: rgb("#0c4842"),
|
||||
alpha: 60%,
|
||||
subslide-preamble: self => block(
|
||||
text(1.2em, weight: "bold", fill: self.colors.primary, utils.display-current-heading(depth: self.slide-level, style: auto)),
|
||||
),
|
||||
..args,
|
||||
body,
|
||||
) = {
|
||||
sidebar = utils.merge-dicts(
|
||||
(width: 10em, filled: false, numbered: false, indent: .5em, short-heading: true),
|
||||
sidebar,
|
||||
)
|
||||
mini-slides = utils.merge-dicts(
|
||||
(height: 4em, x: 2em, display-section: false, display-subsection: true, linebreaks: true, short-heading: true),
|
||||
mini-slides,
|
||||
)
|
||||
set text(size: 20pt)
|
||||
set par(justify: true)
|
||||
|
||||
show: touying-slides.with(
|
||||
config-page(
|
||||
paper: "presentation-" + aspect-ratio,
|
||||
header-ascent: 0em,
|
||||
footer-descent: 0em,
|
||||
margin: if navigation == "sidebar" {
|
||||
(top: 2em, bottom: 1em, x: sidebar.width)
|
||||
} else if navigation == "mini-slides" {
|
||||
(top: mini-slides.height, bottom: 2em, x: mini-slides.x)
|
||||
} else {
|
||||
(top: 2em, bottom: 2em, x: mini-slides.x)
|
||||
},
|
||||
),
|
||||
config-common(
|
||||
slide-fn: slide,
|
||||
new-section-slide-fn: none //new-section-slide,
|
||||
),
|
||||
config-methods(
|
||||
init: (self: none, body) => {
|
||||
show heading: set text(self.colors.primary)
|
||||
|
||||
body
|
||||
},
|
||||
alert: utils.alert-with-primary-color,
|
||||
),
|
||||
config-colors(
|
||||
neutral-darkest: rgb("#000000"),
|
||||
neutral-dark: rgb("#202020"),
|
||||
neutral-light: rgb("#f3f3f3"),
|
||||
neutral-lightest: rgb("#ffffff"),
|
||||
primary: primary,
|
||||
),
|
||||
// save the variables for later use
|
||||
config-store(
|
||||
navigation: navigation,
|
||||
sidebar: sidebar,
|
||||
mini-slides: mini-slides,
|
||||
footer: footer,
|
||||
footer-right: footer-right,
|
||||
alpha: alpha,
|
||||
subslide-preamble: subslide-preamble,
|
||||
),
|
||||
..args,
|
||||
)
|
||||
|
||||
body
|
||||
}
|
69
touying.typ
Normal file
69
touying.typ
Normal file
@ -0,0 +1,69 @@
|
||||
#import "@preview/touying:0.6.1": *
|
||||
#import "/slides/firatheme.typ": *
|
||||
|
||||
#import "@preview/numbly:0.1.0": numbly
|
||||
|
||||
#set text(font: "FiraGO", weight: "light", size: 20pt)
|
||||
#show math.equation: set text(font: "Fira Math")
|
||||
#set strong(delta: 100)
|
||||
#set par(justify: true)
|
||||
|
||||
#show: fira-theme.with(
|
||||
// aspect-ratio: "16-9",
|
||||
// footer: self => self.info.institution,
|
||||
navigation: "mini-slides",
|
||||
config-info(
|
||||
title: [Faster FPTAS for Edge Connectivity
|
||||
Interdiction],
|
||||
// subtitle: [Subtitle],
|
||||
author: [Authors],
|
||||
date: datetime.today(),
|
||||
institution: [Institution],
|
||||
),
|
||||
)
|
||||
|
||||
// #set heading(numbering: numbly("{1}.", default: "1.1"))
|
||||
|
||||
#title-slide()
|
||||
|
||||
#outline-slide()
|
||||
|
||||
= Section A
|
||||
|
||||
== Subsection A.1
|
||||
|
||||
$ x_(n+1) = (x_n + a/x_n) / 2 $
|
||||
|
||||
== Subsection A.2
|
||||
|
||||
A slide without a title but with *important* infos
|
||||
|
||||
= Section B
|
||||
|
||||
== Subsection B.1
|
||||
|
||||
#lorem(80)
|
||||
|
||||
#focus-slide[
|
||||
Wake up!
|
||||
]
|
||||
|
||||
== Subsection B.2
|
||||
|
||||
We can use `#pause` to #pause display something later.
|
||||
|
||||
#pause
|
||||
|
||||
Just like this.
|
||||
|
||||
#meanwhile
|
||||
|
||||
Meanwhile, #pause we can also use `#meanwhile` to #pause display other content synchronously.
|
||||
|
||||
#show: appendix
|
||||
|
||||
= Appendix
|
||||
|
||||
== Appendix
|
||||
|
||||
Please pay attention to the current slide number.
|
Loading…
x
Reference in New Issue
Block a user