Skip to content

Commit

Permalink
Merge pull request #18 from andreasKroepelin/multi-bodies
Browse files Browse the repository at this point in the history
Implement multiple content blocks per slide
  • Loading branch information
andreasKroepelin authored Apr 16, 2023
2 parents c43df34 + 745085a commit 2a4b73c
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 22 deletions.
19 changes: 18 additions & 1 deletion book/src/slide.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,21 @@ These are:
see [here](./dynamic.html#internal-number-of-repetitions)
- additional information used by the theme, see the [gallery](./theme-gallery/index.html)
to find out which they are under your theme's "Extra keyword arguments" section
(typically, you can at least specify a slide title as `title`)
(typically, you can at least specify a slide title as `title`)

## Slides with multiple content bodies
In the vast majority of cases, you will call `#slide` the way described above
with one content block.
However, some [themes](./themes.html) (or some of their
[variants](./themes.html#theme-variants-per-slide)) sometimes require or allow
more than one such content.
In that case, you will write:
```typ
#slide[
The first piece of content
][
Even more content
][
Who knows how much content we can come up with?
]
```
11 changes: 11 additions & 0 deletions book/src/theme-gallery/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
all: default bipartite

default:
pdftoppm ./default.pdf ./default -png
montage ./default-* -geometry +50+50 -background LightGray ./default.png
rm ./default-*

bipartite:
pdftoppm ./bipartite.pdf ./bipartite -png
montage ./bipartite-* -geometry +50+50 -background LightGray ./bipartite.png
rm ./bipartite-*
Binary file modified book/src/theme-gallery/bipartite.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions book/src/theme-gallery/bipartite.typ
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@
#slide(theme-variant: "east", title: "On the right!")[
#lorem(40)
]

#slide(theme-variant: "center split")[
#lorem(40)
][
#lorem(40)
]
Binary file modified book/src/theme-gallery/default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions book/src/theme-gallery/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Here you can find an overview over all themes shipped with this template.
---

## Default
_[go to top](#theme-gallery)_

If you do not specify a theme, the default one will be used.
You can specify it explicitly by referring to `slides-default-theme`:
```typ
Expand Down Expand Up @@ -50,6 +52,8 @@ You can specify it explicitly by referring to `slides-default-theme`:
---

## Bipartite
_[go to top](#theme-gallery)_

This theme is inspired by
[Modern Annual Report](https://slidesgo.com/theme/modern-annual-report).
It features a dominant partition of space into a bright and a dark side.
Expand All @@ -66,6 +70,8 @@ It features a dominant partition of space into a bright and a dark side.
### Variants
- `"east"`: same as default variant, but dark side on the right, text is right
aligned
- `"center split"`: bright left and dark right half of equal size, requires two
content bodies, one for each half (does not display a slide title)

### Extra keyword arguments
- `title`: a title for that slide
Expand All @@ -91,6 +97,12 @@ It features a dominant partition of space into a bright and a dark side.
#slide(theme-variant: "east", title: "On the right!")[
#lorem(40)
]
#slide(theme-variant: "center split")[
#lorem(40)
][
#lorem(40)
]
```
![bipartite theme screenshot](./bipartite.png)

47 changes: 37 additions & 10 deletions book/src/themes.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,15 @@ For example, you could define the title slide in the following way:

On to the actual slides.
Their appearance is defined by functions that accept some meta data, some
content (the last argument to `#slide`, essentially) and return some richer
content, somehow styling that slide.
array of contents (the last argument(s) to `#slide`, essentially) and return
some richer content, somehow styling that slide:
```typ
(dictionary, array of content) => content
```
You can define an arbitrary amount of such functions as values of the `variants`
dictionary, but one of them must be stored under the key `"default"`.

The meta data referred to above are a dictionary containing any extra keyword-
The meta data referred to above are a dictionary containing any extra keyword
arguments that the user has specified in their call to `#slide`.
As a theme author, you should inform your users what kind of arguments you will
respect.
Expand All @@ -101,6 +104,20 @@ then your styling function will be provided the following dictionary:
```
especially not containing a `theme-variant` item!

The `#slide` function accepts an arbitrary amount of positional arguments that
are interpreted as content for the slide.
The user of this template can provide them by simply juxtapositioning multiple
content blocks after `#slide` or `#slide(...)`, see
[this section](./slide.html#slides-with-multiple-content-bodies).
Often, it will make sense to work with only a single piece of content,
however.
In any case, your variant function will always be provided an array of contents
as the second argument, so you will usually have to extract that single entry
you are interested in (using `.at(0)` or `.first()`).
It might also make sense to `panic` with an informative error message if the user
provided another number of content blocks than you expected.


To make use of some of the functionality this template offers, you can access
- the counter `logical-slide`, telling you the "page number" of a slide, but
without counting up on dynamical slides that produce mulitple PDF pages;
Expand All @@ -113,17 +130,23 @@ Let us define two variants:
(
title-slide: align(center + horizon, data.title),
variants: (
"default": (slide-info, body) => {
"default": (slide-info, bodies) => {
text(.7em, [#slide-info.title (current section: #section.display())])
v(1fr)
body
for body in bodies {
body
v(1em)
}
v(1fr)
text(.7em, [#h(1fr) #logical-slide.display()])
},
"australia": (slide-info, body) => {
"australia": (slide-info, bodies) => {
if bodies.len() != 1 {
panic("australia variant expected exactly one body")
}
text(.7em, [current section: #section.display()])
v(1fr)
scale(y: -100%, body)
scale(y: -100%, bodies.first())
v(1fr)
text(.7em, [#h(1fr) #logical-slide.display()])
},
Expand All @@ -139,6 +162,10 @@ The `"australia"` variant does not make use of the `slide-info` argument at all.
That is completely fine, it must have this argument for formal reasons, anyway,
though.

Also, the `"default"` variant displays all the content blocks provided to `#slide`
while the `"australia"` variant errors if more or less than one such block is
given.

And that's it already!
Have fun creating your own theme and maybe consider opening a pull request
at [the GitHub repository](https://github.com/andreasKroepelin/typst-slides)
Expand All @@ -150,14 +177,14 @@ be too limited for what you need.
Sometimes, you might find yourself needing a very special purpose design _just_
for a couple of slides.
For that case, you can use the `override-theme` argument of the `#slide` function.
It accepts a function of the form `(slide-info, body) => [slide content]`, just
It accepts a function of the form `(slide-info, bodies) => [slide content]`, just
as if you would define a theme variant (see details above).

For example, you might write something like this:
```typ
#let special-purpose-theme(slide-info, body) = align(horizon)[
#let special-purpose-theme(slide-info, bodies) = align(horizon)[
#rotate(45deg, heading(level: 2, slide-info.title))
#scale(x: -100%, body)
#scale(x: -100%, bodies.first())
]
#slide(override-theme: special-purpose-theme, title: "This is rotated")[
#lorem(40)
Expand Down
4 changes: 2 additions & 2 deletions examples/override-theme.typ
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
#lorem(40)
]

#let special-purpose-theme(slide-info, body) = align(horizon)[
#let special-purpose-theme(slide-info, bodies) = align(horizon)[
#rotate(45deg, heading(level: 2, slide-info.title))
#scale(x: -100%, body)
#scale(x: -100%, bodies.first())
]
#slide(override-theme: special-purpose-theme, title: "This is rotated")[
#lorem(40)
Expand Down
22 changes: 16 additions & 6 deletions slides.typ
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,7 @@
max-repetitions: 10,
theme-variant: "default",
override-theme: none,
..kwargs,
body
..args
) = {
pagebreak(weak: true)
logical-slide.step()
Expand All @@ -191,15 +190,16 @@
if override-theme != none {
slide-content = override-theme
}
let slide-info = kwargs.named()
let slide-info = args.named()
let bodies = args.pos()

for _ in range(max-repetitions) {
locate( loc-inner => {
let curr-subslide = subslide.at(loc-inner).first()
if curr-subslide <= repetitions.at(loc-inner).first() {
if curr-subslide > 1 { pagebreak(weak: true) }

slide-content(slide-info, body)
slide-content(slide-info, bodies)
}
})
subslide.step()
Expand Down Expand Up @@ -240,7 +240,12 @@
]
}

let default(slide-info, body) = {
let default(slide-info, bodies) = {
if bodies.len() != 1 {
panic("default variant of default theme only supports one body per slide")
}
let body = bodies.first()

let decoration(position, body) = {
let border = 1mm + color
let strokes = (
Expand Down Expand Up @@ -283,7 +288,12 @@
]
}

let wake-up(slide-info, body) = {
let wake-up(slide-info, bodies) = {
if bodies.len() != 1 {
panic("wake up variant of default theme only supports one body per slide")
}
let body = bodies.first()

block(
width: 100%, height: 100%, inset: 2em, breakable: false, outset: 0em,
fill: color,
Expand Down
35 changes: 32 additions & 3 deletions themes/bipartite.typ
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@
[]
}

let west(slide-info, body) = {
let west(slide-info, bodies) = {
if bodies.len() != 1 {
panic("default variant of bipartite theme only supports one body per slide")
}
let body = bodies.first()

box(
width: 30%, height: 100%, outset: 0em, inset: (x: 1em), baseline: 0em,
stroke: none, fill: my-dark,
Expand All @@ -47,7 +52,12 @@
)
}

let east(slide-info, body) = {
let east(slide-info, bodies) = {
if bodies.len() != 1 {
panic("east variant of bipartite theme only supports one body per slide")
}
let body = bodies.first()

box(
width: 70%, height: 100%, outset: 0em, inset: (x: 1em), baseline: 0em,
stroke: none, fill: my-bright,
Expand All @@ -60,8 +70,27 @@
)
}

let center-split(slide-info, bodies) = {
if bodies.len() != 2 {
panic("center split variant of bipartite theme only supports two bodies per slide")
}
let body-left = bodies.first()
let body-right = bodies.last()

box(
width: 50%, height: 100%, outset: 0em, inset: (x: 1em), baseline: 0em,
stroke: none, fill: my-bright,
align(right + horizon, text(fill: my-dark, body-left))
)
box(
width: 50%, height: 100%, outset: 0em, inset: (x: 1em), baseline: 0em,
stroke: none, fill: my-dark,
align(left + horizon, text(fill: my-bright, body-right))
)
}

(
title-slide: title-slide,
variants: ( "default": west, "east": east ),
variants: ( "default": west, "east": east, "center split": center-split ),
)
}

0 comments on commit 2a4b73c

Please sign in to comment.