Skip to content

Commit 8e4c61d

Browse files
authored
parcio-slides:0.1.2 and parcio-thesis:0.2.3 (#3236)
1 parent 71ed822 commit 8e4c61d

File tree

33 files changed

+2538
-0
lines changed

33 files changed

+2538
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
BSD Zero Clause License
2+
3+
Copyright (c) 2025 xkevio
4+
5+
Permission to use, copy, modify, and/or distribute this software for any
6+
purpose with or without fee is hereby granted.
7+
8+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14+
PERFORMANCE OF THIS SOFTWARE.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# The `parcio-slides` Polylux Template
2+
3+
<p align="center">
4+
<img src="thumbnails/cover.png" width=40%>
5+
<img src="thumbnails/main-02.png" width=40%><br/>
6+
<img src="thumbnails/main-03.png" width=40%>
7+
<img src="thumbnails/main-04.png" width=40%>
8+
</p>
9+
10+
<p align="center">
11+
A simple <a href="https://typst.app/universe/package/polylux/">polylux</a> slides template based on the ParCIO working group at Otto-von-Guericke University Magdeburg.
12+
</p>
13+
14+
## Getting Started
15+
16+
To use this template, simply import it as shown below and define a `title-slide` with the following possible options:
17+
18+
```typ
19+
#import "@preview/parcio-slides:0.1.2": *
20+
21+
#show: parcio-theme.with(
22+
aspect-ratio: "16-9", // "16-9" and "4-3" are the only possible options.
23+
text-size: 20pt, // We recommend around this text size, as it fits nicely.
24+
)
25+
26+
#title-slide(
27+
title: [],
28+
author: (name: "Your Name", mail: "example@ovgu.de"),
29+
subtitle: none,
30+
short-title: none,
31+
logo: none,
32+
date: datetime.today().display(),
33+
extra: none
34+
)
35+
```
36+
37+
These are the default options. We recommend leaving the show-rule as-is, such that you can just do `#show parcio-theme`, and
38+
using the provided OvGU logo for your title slide (if you initialized with `typst init`) by specifying `logo: image("ovgu.svg", width: 9.8cm)`
39+
on your title slide.
40+
41+
Multiple authors can be displayed by providing an array of dictionaries instead, like so:
42+
```typ
43+
...
44+
author: (
45+
(name: "Author One", mail: "author.one@ovgu.de"),
46+
(name: "Author Two", mail: "author.two@ovgu.de")
47+
),
48+
...
49+
```
50+
51+
The `short-title` is useful for specifying a shorter title which is displayed in the footer of each slide.
52+
Additionally, `extra` can be used for specifying your lecture, institute or faculty. See `template/main.typ` for a full example!
53+
54+
### Slides
55+
56+
Creating slides is done via the `#slide()`-function with the following default arguments:
57+
58+
```typ
59+
#slide(
60+
title: none, // title of your current slide
61+
new-section: none, // marks a new topic, add it to the outline and is displayed in the top-right
62+
show-current-section: true, // whether to display the current section in the top-right
63+
show-footer: true, // whether to display the footer (disabled for `bib-slide` and `outline-slide`)
64+
skip: false, // whether to skip the page counter for this slide
65+
body,
66+
)
67+
```
68+
69+
Most often, you will use `#slide` like this: `#slide(title: "Introduction")[...]`—setting a title is important for the header bar to properly work!
70+
71+
#### Outline and Bibliography Slides
72+
73+
- You can use `#outline-slide(title: "Outline")` to create a slide which lists all of your sections you registered with `new-section`!
74+
- You can use `#bib-slide(title: "References", bib)` to create a slide containing your bibliography. This slide will have slightly smaller text, justified paragraphs and expects
75+
the actual `bibliography(..)` function call as a second argument.
76+
77+
#### Using `polylux` functions
78+
79+
In order to use `polylux` functions for dynamic slide management, such as `show: later` or `uncover`, importing those functions separately is necessary.
80+
Additionally, this template uses a different page counter than that of `polylux`, so to achieve the correct dynamic slide numbering, manual fiddling is required
81+
(the counter is accessible through `#counter("m-page")`).
82+
83+
### Local Installation
84+
85+
Following these steps will make the template available locally under the `@local` namespace. Requires ["Just - A Command Runner"](https://github.com/casey/just).
86+
87+
```sh
88+
git clone git@github.com:xkevio/parcio-typst.git
89+
cd parcio-typst/parcio-slides/
90+
just install
91+
```
92+
93+
## Fonts and OvGU Corporate Design
94+
95+
This template requires these two fonts to be installed on your system:
96+
97+
* Libertinus Sans (https://github.com/alerque/libertinus)
98+
* Inconsolata (https://github.com/googlefonts/Inconsolata)
99+
100+
We bundle the default "Faculty of Computer Science" head banner and use it as the `logo`. You can find yours at: https://www.cd.ovgu.de/Fakult%C3%A4ten.html.
101+
Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
#import "@preview/polylux:0.4.0": slide as polylux-slide, toolbox
2+
#import "@preview/subpar:0.2.2"
3+
4+
#let m-dark-teal = rgb("#23373b")
5+
#let m-light-brown = rgb("#eb811b")
6+
#let m-lighter-brown = rgb("#d6c6b7")
7+
#let m-extra-light-gray = white.darken(2%)
8+
9+
#let ovgu-red = rgb("#D13F58")
10+
#let ovgu-purple = rgb("#7A003F")
11+
#let ovgu-blue = rgb("#0068B4")
12+
#let ovgu-darkgray = rgb("#606060")
13+
#let ovgu-lightgray = rgb("#C0C0C0").lighten(50%)
14+
#let ovgu-orange = rgb("#F39100")
15+
16+
#let m-pages = counter("m-page")
17+
#let m-footer = state("m-footer", [])
18+
#let m-metadata = state("m-metadata", (:))
19+
20+
#let m-progress-bar = context {
21+
let ratio = m-pages.get().first() / m-pages.final().first()
22+
grid(
23+
columns: (ratio * 100%, 1fr),
24+
rect(fill: ovgu-purple, width: 100%),
25+
rect(fill: m-lighter-brown, width: 100%),
26+
)
27+
}
28+
29+
/* ----- General theming and show rules ----- */
30+
31+
#let parcio-theme(aspect-ratio: "16-9", text-size: 20pt, body) = {
32+
set page(
33+
paper: "presentation-" + aspect-ratio,
34+
margin: 0em,
35+
header: none,
36+
footer: none,
37+
)
38+
39+
set text(font: "Libertinus Sans", fill: m-dark-teal, text-size)
40+
set list(indent: 1em)
41+
set enum(indent: 1em)
42+
43+
show raw: set text(font: "Inconsolata", 1.1em)
44+
45+
// Add line numbers to code block.
46+
show raw.where(block: true): r => {
47+
show raw: set par(leading: 0.75em)
48+
show raw.line: l => {
49+
box(table(
50+
columns: (-1.25em, 100%),
51+
stroke: 0pt,
52+
inset: 0em,
53+
column-gutter: 1em,
54+
align: (x, y) => if x == 0 { right } else { left },
55+
text(fill: ovgu-darkgray, str(l.number)),
56+
l.body,
57+
))
58+
}
59+
60+
set align(left)
61+
block(width: 100%, stroke: gray + 0.5pt, inset: 0.75em, r)
62+
}
63+
64+
// Display supplement in bold.
65+
show figure.caption: c => context [
66+
*#c.supplement #c.counter.display(c.numbering)#c.separator*#c.body
67+
]
68+
69+
// Make URLs use monospaced font.
70+
show link: it => { set text(font: "Inconsolata", 0.9em) if type(it.dest) == str; it }
71+
72+
set footnote.entry(
73+
indent: 2.5em,
74+
separator: line(start: (2em, 0em), end: (40%, 0em), stroke: 0.5pt),
75+
)
76+
77+
body
78+
}
79+
80+
// Declare your title slide! OvGU logo to the right.
81+
//
82+
// - title: Your presentation title.
83+
// - author: Consists of author.name and author.mail.
84+
// - subtitle: (Optional) subtitle for more info.
85+
// - short-title: (Optional) short title for the footer.
86+
// - logo: (Optional) institution / faculty logo
87+
// - date: (Optional) date of the presentation.
88+
// - extra: (Optional) info below the date, like your faculty.
89+
#let title-slide(
90+
title: [],
91+
author: (name: "Your Name", mail: "example@ovgu.de"),
92+
subtitle: none,
93+
short-title: none,
94+
logo: none,
95+
date: datetime.today().display(),
96+
extra: none,
97+
) = {
98+
m-metadata.update(("title": title, "authors": author))
99+
let content = {
100+
set align(horizon)
101+
102+
v(-1em)
103+
block(width: 100%, inset: 2.5em, height: 100%, {
104+
// Upper part: Title, subtitle and logo.
105+
grid(
106+
columns: (auto, 1fr),
107+
align: (left, right),
108+
text(size: 1.3em, strong(title) + v(-0.25em) + text(0.85em, subtitle)),
109+
logo,
110+
)
111+
112+
// Middle part: line separator.
113+
v(0.5em)
114+
line(length: 100%, stroke: 0.75pt + ovgu-purple)
115+
v(1.5em)
116+
117+
// Bottom part: Author, date, institution, etc.
118+
set text(size: .9em)
119+
120+
let author-information = if type(author) == array {
121+
let names = author.map(x => x.name)
122+
let mails = author.map(x => x.mail)
123+
124+
let name-and-mail = names.zip(mails).map(
125+
((n, m)) => n + "\n" + link("mailto:" + m)
126+
)
127+
128+
grid(columns: author.len(), column-gutter: 1em, ..name-and-mail)
129+
} else {
130+
author.name + "\n" + link("mailto:" + author.mail)
131+
}
132+
133+
stack(spacing: 1em, author-information, date, extra)
134+
})
135+
}
136+
137+
m-footer.update(
138+
grid(columns: (1fr, auto, 1fr), align: (left, center, right),
139+
if type(author) == array { author.map(x => x.name).join(", ") } else { author.name },
140+
if short-title != none { short-title } else { title },
141+
context [#m-pages.get().first() / #m-pages.final().first()]
142+
),
143+
)
144+
145+
polylux-slide(content)
146+
}
147+
148+
// Basic slide function.
149+
//
150+
// - title: (Optional) title of the slide, will be shown on the left in the header.
151+
// - new-section: (Optional) marks a new topic, adds it to the outline & on the right in the header.
152+
// - show-current-section: (default: true) if the current section should be displayed.
153+
// - show-footer: (default: true) if the footer should be displayed.
154+
// - skip: (default: false) whether to skip the page counter for this slide
155+
#let slide(
156+
title: none,
157+
new-section: none,
158+
show-current-section: true,
159+
show-footer: true,
160+
skip: false,
161+
body,
162+
) = {
163+
// Define header: [Subsection] --- [Section], incl. progress bar.
164+
let header = {
165+
set align(top)
166+
167+
if title != none {
168+
if new-section != none {
169+
toolbox.register-section(new-section)
170+
}
171+
172+
if not skip {
173+
m-pages.step()
174+
}
175+
176+
block(fill: ovgu-lightgray, inset: 1em, width: 100%, height: 100%)[
177+
#set align(horizon)
178+
#set text(fill: ovgu-blue, 1em)
179+
180+
*#title*#h(1fr)
181+
#if show-current-section [
182+
#text(0.75em)[*#toolbox.current-section*]
183+
]
184+
]
185+
} else {
186+
strong("Missing Headline")
187+
}
188+
189+
block(height: 1pt, width: 100%, spacing: 0pt, m-progress-bar)
190+
}
191+
192+
// Define footer: [author] - [title] - [page / total]
193+
let footer = if show-footer {
194+
show: pad.with(bottom: .25em, rest: .35em)
195+
align(bottom, text(0.7em, context m-footer.get()))
196+
}
197+
198+
set page(
199+
header: header,
200+
footer: footer,
201+
header-ascent: 0em,
202+
margin: (top: 2.5em, bottom: 1em),
203+
fill: m-extra-light-gray,
204+
)
205+
206+
let content = {
207+
show: align.with(horizon)
208+
show: pad.with(2em)
209+
body
210+
}
211+
212+
polylux-slide(content)
213+
}
214+
215+
/* ----- Helper / Utility functions for tables, subfigures, shortcuts & todos. ----- */
216+
217+
// Creates a clickable outline with a customizable title for each `new-section` entry.
218+
// - `show-title`: Whether to show the presentation title as a heading (default: false)
219+
// - `new-section`: The next section to highlight in the outline-slide (default: none)
220+
#let outline-slide(title: "Outline", show-title: false, new-section: none) = slide(
221+
title: title,
222+
show-footer: false,
223+
skip: true,
224+
[
225+
#set list(marker: none, spacing: 2em)
226+
#set text(gray) if new-section != none
227+
228+
#if show-title [
229+
- #text(m-dark-teal, context m-metadata.get().title)
230+
]
231+
232+
- #toolbox.all-sections((s, c) => list(
233+
..s.map(x => if x.body.text == new-section { text(m-dark-teal, x) } else { x })
234+
))
235+
]
236+
)
237+
238+
// Creates a list of all references using the given style.
239+
#let bib-slide(title: "References", bibliography) = slide(
240+
title: title,
241+
show-footer: false,
242+
show-current-section: false,
243+
skip: true
244+
)[
245+
#set grid(align: top)
246+
#set par(justify: true)
247+
#set text(0.9em)
248+
#bibliography
249+
]
250+
251+
// Custom ParCIO table as illustrated in the template.
252+
#let parcio-table(max-rows, ..args) = table(
253+
..args,
254+
row-gutter: (2.5pt, auto),
255+
stroke: (x, y) => (
256+
left: 0.5pt,
257+
right: 0.5pt,
258+
top: if y <= 1 { 0.5pt },
259+
bottom: if y == 0 or y == max-rows - 1 { 0.5pt }
260+
)
261+
)
262+
263+
// Simple orange TODO box.
264+
#let todo = rect.with(fill: ovgu-orange, stroke: black + 0.5pt, radius: 0.25em, width: 100%)

0 commit comments

Comments
 (0)