diff --git a/changelog.md b/changelog.md index 87030a162..be5613796 100644 --- a/changelog.md +++ b/changelog.md @@ -6,10 +6,11 @@ sidebar_position: 14 ## v0.3.2 -1. **fix critical bug:** fix `is-sequence` function, make `grid` and `table` work correctly in touying -2. **theme:** add aqua theme, thanks for pride7 -3. **refactor:** don't export variable `s` by default anymore, it will be extracted by `register` function (**Breaking Change**) -4. **meta:** add `categories` and `template` config to `typst.toml` for Typst 0.11 +- **fix critical bug:** fix `is-sequence` function, make `grid` and `table` work correctly in touying +- **theme:** add aqua theme, thanks for pride7 +- **theme:** make university theme more configurable +- **refactor:** don't export variable `s` by default anymore, it will be extracted by `register` function (**Breaking Change**) +- **meta:** add `categories` and `template` config to `typst.toml` for Typst 0.11 ## v0.3.1 diff --git a/docs/docs/changelog.md b/docs/docs/changelog.md index 87030a162..be5613796 100644 --- a/docs/docs/changelog.md +++ b/docs/docs/changelog.md @@ -6,10 +6,11 @@ sidebar_position: 14 ## v0.3.2 -1. **fix critical bug:** fix `is-sequence` function, make `grid` and `table` work correctly in touying -2. **theme:** add aqua theme, thanks for pride7 -3. **refactor:** don't export variable `s` by default anymore, it will be extracted by `register` function (**Breaking Change**) -4. **meta:** add `categories` and `template` config to `typst.toml` for Typst 0.11 +- **fix critical bug:** fix `is-sequence` function, make `grid` and `table` work correctly in touying +- **theme:** add aqua theme, thanks for pride7 +- **theme:** make university theme more configurable +- **refactor:** don't export variable `s` by default anymore, it will be extracted by `register` function (**Breaking Change**) +- **meta:** add `categories` and `template` config to `typst.toml` for Typst 0.11 ## v0.3.1 diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/current/changelog.md b/docs/i18n/zh/docusaurus-plugin-content-docs/current/changelog.md index 7b4aa1a1c..c6da68654 100644 --- a/docs/i18n/zh/docusaurus-plugin-content-docs/current/changelog.md +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/current/changelog.md @@ -6,10 +6,11 @@ sidebar_position: 14 ## v0.3.2 -1. **fix critical bug:** fix `is-sequence` function, make `grid` and `table` work correctly in touying -2. **theme:** add aqua theme, thanks for pride7 -3. **refactor:** don't export variable `s` by default anymore, it will be extracted by `register` function (**Breaking Change**) -4. **meta:** add `categories` and `template` config to `typst.toml` for Typst 0.11 +- **fix critical bug:** fix `is-sequence` function, make `grid` and `table` work correctly in touying +- **theme:** add aqua theme, thanks for pride7 +- **theme:** make university theme more configurable +- **refactor:** don't export variable `s` by default anymore, it will be extracted by `register` function (**Breaking Change**) +- **meta:** add `categories` and `template` config to `typst.toml` for Typst 0.11 ## v0.3.1 diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/build-your-own-theme.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/build-your-own-theme.md new file mode 100644 index 000000000..04c32c54d --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/build-your-own-theme.md @@ -0,0 +1,434 @@ +--- +sidebar_position: 10 +--- + +# 创建自己的主题 + +使用 Touying 创建一个自己的主题是一件略显复杂的事情,因为我们引入了许多的概念。不过请放心,如果您真的用 Touying 创建了一个自己的主题,也许您就可以深切地感受到 Touying 提供的便利的功能的和强大的可定制性。您可以参考 [主题的源代码](https://github.com/touying-typ/touying/tree/main/themes),主要需要实现的就是: + +- 自定义 `register` 函数,初始化全局单例 `s`; +- 自定义 `init` 方法; +- 自定义颜色主题,即修改 `self.colors` 成员变量; +- 自定义 `alert` 方法,可选; +- 自定义 header; +- 自定义 footer; +- 自定义 `slide` 方法; +- 自定义特殊 slide 方法,如 `title-slide` 和 `focus-slide` 方法; +- 自定义 `slides` 方法,可选; + +为了演示如何使用 Touying 创建一个自己的主题,我们不妨来一步一步地创建一个简洁美观的 Bamboo 主题。 + + +## 导入 + +取决于这个主题是你自己的,还是 Touying 的一部分,你可以用两种方式导入: + +如果只是你自己使用,你可以直接导入 Touying: + +```typst +#import "@preview/touying:0.3.2": * +``` + +如果你希望这个主题作为 Touying 的一部分,放置在 Touying `themes` 目录下,那你应该将上面的导入语句改为 + +```typst +#import "../utils/utils.typ" +#import "../utils/states.typ" +#import "../utils/components.typ" +``` + +并且要在 Touying 的 `themes/themes.typ` 里加上 + +``` +#import "bamboo.typ" +``` + + +## register 函数和 init 方法 + +接下来,我们会区分 `bamboo.typ` 模板文件和 `main.typ` 文件,后者有时会被省略。 + +一般而言,我们制作 slides 的第一步,就是确定好字体大小和页面长宽比,因此我们需要注册一个初始化方法: + +```typst +// bamboo.typ +#import "@preview/touying:0.3.2": * + +#let register( + self: themes.default.register(), + aspect-ratio: "16-9", +) = { + self.page-args += ( + paper: "presentation-" + aspect-ratio, + ) + self.methods.init = (self: none, body) => { + set text(size: 20pt) + body + } + self +} + +// main.typ +#import "@preview/touying:0.3.2": * +#import "bamboo.typ" + +#let s = bamboo.register(aspect-ratio: "16-9") +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide,) = utils.slides(s) +#show: slides + += First Section + +== First Slide + +#slide[ + A slide with a title and an *important* information. +] +``` + +如您所见,我们创建了一个 `register` 函数,并传入了一个 `aspect-ratio` 参数来设定页面长宽比。我们使用 `self: themes.default.register()` 的方式,获得了缺省的 `self`。然后我们就需要设置页面参数了。您应该已经知道了,在 Touying 中,我们不应该使用 `set page(..)` 来设置页面参数,而是应该使用 ` self.page-args += (..)` 这种语法来设置,具体内容可以参考页面布局章节。 + +除此之外,我们还注册了一个 `self.methods.init` 方法,它可以用来进行一些全局的样式设置,例如在此处,我们加上了 `set text(size: 20pt)` 来设置文字大小。你也可以在这里放置一些额外的全局样式设置,例如 `set par(justify: true)` 等。由于 `init` 函数被放置到了 `self.methods` 里,是一个方法,而非普通函数,因此我们需要加上 `self: none` 参数才能正常使用。 + +如您所见,后续在 `main.typ` 中,我们会通过 `#show: init` 来应用 `init` 方法里面的全局样式设置,其中 `init` 函数是通过 `utils.methods(s)` 绑定并解包而来的。 + +如果您多加注意,您会发现 `register` 函数最后有一行独立的 `self`,这其实是代表了将修改后的 `self` 作为返回值返回,后续会被保存在 `#let s = ..` 中,因此这一行是不可或缺的。 + + +## 颜色主题 + +为您的 slides 挑选一个美观的颜色主题,是做好一个 slides 的关键所在。Touying 提供了内置的颜色主题支持,以尽量抹平不同主题之间的 API 差异。Touying 提供了两个维度的颜色选择,第一个维度是 `neutral`、`primary`、`secondary` 和 `tertiary`,用于区分色调,其中最常用的就是 `primary` 主题色;第二个维度是 `default`、`light`、`lighter`、`lightest`、`dark`、`darker`、`darkest`,用于区分明度。 + +由于我们是 Bamboo 主题,因此这里的主题色 `primary` 我们挑选了一个与竹子相近的颜色 `rgb("#5E8B65")`,并加入了中性色 `neutral-lightest`,`neutral-darkest`,分别作为背景色和字体颜色。 + +正如下面的代码所示,我们可以使用 `self = (self.methods.colors)(self: self, ..)` 方法修改颜色主题。其本质就是 `self.colors += (..)` 的一个包装。 + +```typst +#let register( + self: themes.default.register(), + aspect-ratio: "16-9", +) = { + // color theme + self = (self.methods.colors)( + self: self, + primary: rgb("#5E8B65"), + neutral-lightest: rgb("#ffffff"), + neutral-darkest: rgb("#000000"), + ) + self.page-args += ( + paper: "presentation-" + aspect-ratio, + ) + self.methods.init = (self: none, body) => { + set text(size: 20pt) + body + } + self +} +``` + +像这样添加了颜色主题后,我们就可以通过 `self.colors.primary` 这样的方式获取到这个颜色。 + +并且有一点值得注意,用户可以随时在 `main.typ` 里通过 + +```typst +#let s = (s.methods.colors)(self: s, primary: rgb("#3578B9")) +``` + +这样的方式修改主题色,其中这句语句需要放在 `register()` 之后,以及 `utils.methods(s)` 之前。 + +这种随时更换颜色主题的内容,正是 Touying 强大可定制性的体现。 + + +## 实战:自定义 Alert 方法 + +一般而言,我们都需要提供一个 `#alert[..]` 函数给用户使用,其用途与 `#strong[..]` 类似,都是用于强调当前文本。一般 `#alert[..]` 会将文本颜色修改为主题色,这样看起来会更美观,这也是我们接下来要实现的目标。 + +我们在 `register` 函数里加上一句 + +```typst +self.methods.alert = (self: none, it) => text(fill: self.colors.primary, it) +``` + +这句代码的意思就是将文本颜色修改为 `self.colors.primary`,而这里的 `self` 正是通过参数 `self: none` 传进来的,这样我们才能实时地获取到 `primary` 主题色。 + + +## 自定义 Header 和 Footer + +在这里,我认为您已经阅读过页面布局章节了,因此我们知道应该给 slides 加上 header 和 footer。 + +首先,我们先加入 `self.bamboo-title = []`,也就是说,我们将当前 slide 的标题作为一个成员变量 `self.bamboo-title`,保存在 `self` 里面,这样方便我们在 header 里使用,以及后续修改。同理,我们还创建了一个 `self.bamboo-footer`,并将 `register` 函数的 `footer: []` 参数保存起来,用作左下角的 footer 展示。 + +然后值得注意的就是,我们的 header 其实是一个形如 `let header(self) = { .. }` 的参数为 `self` 的 content 函数,而不是一个单纯的 content,这样我们才能从最新的 `self` 内部获取到我们需要的信息,例如 `self.bamboo-title`。而 footer 也是同理。 + +里面使用到的 `components.cell` 其实就是 `#let cell = block.with(width: 100%, height: 100%, above: 0pt, below: 0pt, breakable: false)`,而 `show: components.cell` 也就是 `components.cell(body)` 的简写,footer 的 `show: pad.with(.4em)` 也是同理。 + +另一点值得注意的是,`states` 模块里放置了很多和计数器、状态有关的内容,例如 `states.current-section-title` 用于显示当前的 `section`,而 `states.slide-counter.display() + " / " + states.last-slide-number` 用于显示当前页数和总页数。 + +以及我们发现我们会使用 `utils.call-or-display(self, self.bamboo-footer)` 这样的语法来显示 `self.bamboo-footer`,这是用于应付 `self.bamboo-footer = (self) => {..}` 这种情况,这样我们就能统一 content 函数和 content 的显示。 + +为了让 header 和 footer 正确显示,并且与正文有足够的间隔,我们还设置了上下 margin 和左右 padding,如 `self.page-args += (margin: (top: 4em, bottom: 1.5em, x: 0em))` 和 `self.padding = (x: 2em, y: 0em)`。左右 margin 为 `0em` 是为了让 header 能占满页面宽度,正文的左右间距就依靠左右 padding `2em` 来实现。 + +而我们还需要自定义一个 `slide` 方法,其中接收 `slide(self: none, title: auto, ..args)`,第一个 `self: none` 是一个方法所必须的参数,用于获取最新的 `self`;而第二个 `title` 则是用于更新 `self.bamboo-title`,以便在 header 中显示出来;第三个 `..args` 是用于收集剩余的参数,并传到 `(self.methods.touying-slide)(self: self, ..args)` 里,这也是让 Touying `slide` 功能正常生效所必须的。并且,我们需要在 `register` 函数里使用 `self.methods.slide = slide` 注册这个方法。 + +```typst +// bamboo.typ +#import "@preview/touying:0.3.2": * + +#let slide(self: none, title: auto, ..args) = { + if title != auto { + self.bamboo-title = title + } + (self.methods.touying-slide)(self: self, ..args) +} + +#let register( + self: themes.default.register(), + aspect-ratio: "16-9", + footer: [], +) = { + // color theme + self = (self.methods.colors)( + self: self, + primary: rgb("#5E8B65"), + neutral-lightest: rgb("#ffffff"), + neutral-darkest: rgb("#000000"), + ) + // variables for later use + self.bamboo-title = [] + self.bamboo-footer = footer + // set page + let header(self) = { + set align(top) + show: components.cell.with(fill: self.colors.primary, inset: 1em) + set align(horizon) + set text(fill: self.colors.neutral-lightest, size: .7em) + states.current-section-title + linebreak() + set text(size: 1.5em) + utils.call-or-display(self, self.bamboo-title) + } + let footer(self) = { + set align(bottom) + show: pad.with(.4em) + set text(fill: self.colors.neutral-darkest, size: .8em) + utils.call-or-display(self, self.bamboo-footer) + h(1fr) + states.slide-counter.display() + " / " + states.last-slide-number + } + self.page-args += ( + paper: "presentation-" + aspect-ratio, + header: header, + footer: footer, + margin: (top: 4em, bottom: 1.5em, x: 0em), + ) + self.padding = (x: 2em, y: 0em) + // register methods + self.methods.slide = slide + self.methods.alert = (self: none, it) => text(fill: self.colors.primary, it) + self.methods.init = (self: none, body) => { + set text(size: 20pt) + body + } + self +} + + +// main.typ +#import "@preview/touying:0.3.2": * +#import "bamboo.typ" + +#let s = bamboo.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide,) = utils.slides(s) +#show: slides + += First Section + +== First Slide + +#slide[ + A slide with a title and an *important* information. +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/d33bcda7-c032-4b11-b392-5b939d9a0a47) + + +## 自定义特殊 Slide + +我们在上面的基础 slide 的基础上,进一步加入一些特殊的 slide 函数,例如 `title-slide`,`focus-slide` 以及自定义 `slides` 方法。 + +对于 `title-slide` 方法,首先,我们调用了 `self = utils.empty-page(self)`,这个函数可以清除 `self.page-args.header` 和 `self.page-args.footer`,以及将 `margin` 和 `padding` 都设为 `0em`,得到一个空白页的效果。然后,我们可以通过 `let info = self.info + args.named()` 获取到 `self.info` 里保存的信息,也可以用函数参数里传入的 `args.named()` 来更新信息,便于后续以 `info.title` 的方式使用。具体的页面内容 `body`,每个 theme 都会有所不同,这里就不再过多赘述。而在最后,我们调用了 `(self.methods.touying-slide)(self: self, repeat: none, body)`,其中的 `repeat: none` 表面这个页面不需要动画效果,而传入 `body` 参数会将 `body` 的内容显示出来。 + +对于 `new-section-slide` 方法,也是同理,不过唯一要注意的是我们在 `(self.methods.touying-slide)(self: self, repeat: none, section: section, body)` 的参数里面多传入了一个 `section: section`,这是用来声明新建一个 `section` 的。另一点需要注意的是,我们除了 `self.methods.new-section-slide = new-section-slide`,还注册了 `self.methods.touying-new-section-slide = new-section-slide`,这样 `new-section-slide` 就会在碰到一级标题时自动被调用。 + +对于 `focus-slide` 方法,大部分内容也基本一致,不过值得注意的是,我们通过 `self.page-args += (..)` 更新了页面的背景颜色。 + +最后,我们还更新了 `slides(self: none, title-slide: true, slide-level: 1, ..args)` 方法,其中 `title-slide` 为 `true` 时,在使用 `#show: slides` 后会自动创建一个 `title-slide`;而 `slide-level: 1` 指明了一级标题和二级标题分别对应 `section` 和 `title`。 + +``` +// bamboo.typ +#import "@preview/touying:0.3.2": * + +#let slide(self: none, title: auto, ..args) = { + if title != auto { + self.bamboo-title = title + } + (self.methods.touying-slide)(self: self, ..args) +} + +#let title-slide(self: none, ..args) = { + self = utils.empty-page(self) + let info = self.info + args.named() + let body = { + set align(center + horizon) + block( + fill: self.colors.primary, + width: 80%, + inset: (y: 1em), + radius: 1em, + text(size: 2em, fill: self.colors.neutral-lightest, weight: "bold", info.title) + ) + set text(fill: self.colors.neutral-darkest) + if info.author != none { + block(info.author) + } + if info.date != none { + block(if type(info.date) == datetime { info.date.display(self.datetime-format) } else { info.date }) + } + } + (self.methods.touying-slide)(self: self, repeat: none, body) +} + +#let new-section-slide(self: none, section) = { + self = utils.empty-page(self) + let body = { + set align(center + horizon) + set text(size: 2em, fill: self.colors.primary, weight: "bold", style: "italic") + section + } + (self.methods.touying-slide)(self: self, repeat: none, section: section, body) +} + +#let focus-slide(self: none, body) = { + self = utils.empty-page(self) + self.page-args += ( + fill: self.colors.primary, + margin: 2em, + ) + set text(fill: self.colors.neutral-lightest, size: 2em) + (self.methods.touying-slide)(self: self, repeat: none, align(horizon + center, body)) +} + +#let slides(self: none, title-slide: true, slide-level: 1, ..args) = { + if title-slide { + (self.methods.title-slide)(self: self) + } + (self.methods.touying-slides)(self: self, slide-level: slide-level, ..args) +} + +#let register( + self: themes.default.register(), + aspect-ratio: "16-9", + footer: [], +) = { + // color theme + self = (self.methods.colors)( + self: self, + primary: rgb("#5E8B65"), + neutral-lightest: rgb("#ffffff"), + neutral-darkest: rgb("#000000"), + ) + // variables for later use + self.bamboo-title = [] + self.bamboo-footer = footer + // set page + let header(self) = { + set align(top) + show: components.cell.with(fill: self.colors.primary, inset: 1em) + set align(horizon) + set text(fill: self.colors.neutral-lightest, size: .7em) + states.current-section-title + linebreak() + set text(size: 1.5em) + utils.call-or-display(self, self.bamboo-title) + } + let footer(self) = { + set align(bottom) + show: pad.with(.4em) + set text(fill: self.colors.neutral-darkest, size: .8em) + utils.call-or-display(self, self.bamboo-footer) + h(1fr) + states.slide-counter.display() + " / " + states.last-slide-number + } + self.page-args += ( + paper: "presentation-" + aspect-ratio, + header: header, + footer: footer, + margin: (top: 4em, bottom: 1.5em, x: 0em), + ) + self.padding = (x: 2em, y: 0em) + // register methods + self.methods.slide = slide + self.methods.title-slide = title-slide + self.methods.new-section-slide = new-section-slide + self.methods.touying-new-section-slide = new-section-slide + self.methods.focus-slide = focus-slide + self.methods.slides = slides + self.methods.alert = (self: none, it) => text(fill: self.colors.primary, it) + self.methods.init = (self: none, body) => { + set text(size: 20pt) + body + } + self +} + + +// main.typ +#import "@preview/touying:0.3.2": * +#import "bamboo.typ" + +#let s = bamboo.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, focus-slide) = utils.slides(s) +#show: slides + += First Section + +== First Slide + +#slide[ + A slide with a title and an *important* information. +] + +#focus-slide[ + Focus on it! +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/03c5ad02-8ff4-4068-9664-d9cfad79baaf) + + +## 总结 + +至此,我们就已经创建了一个简洁又美观的主题了。也许你会觉得,Touying 引入的概念过于丰富了,以至于让人一时很难轻易接受。这是正常的,在强大的功能与简洁的概念之间,Touying 选择了前者。但是也正是得益于 Touying 这种大而全的统一理念,你可以很容易地在不同的主题之间抽离出共通之处,并将你学到的概念迁移到另一个主题上。亦或者,你可以很轻易地保存全局变量,或者更改已有的主题,例如全局保存主题颜色,替换掉 slides 的 header,或者添加一两个 Logo 等,这也正是 Touying 解耦与面向对象编程带来的好处。 \ No newline at end of file diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/changelog.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/changelog.md new file mode 100644 index 000000000..c6da68654 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/changelog.md @@ -0,0 +1,81 @@ +--- +sidebar_position: 14 +--- + +# 更新日志 + +## v0.3.2 + +- **fix critical bug:** fix `is-sequence` function, make `grid` and `table` work correctly in touying +- **theme:** add aqua theme, thanks for pride7 +- **theme:** make university theme more configurable +- **refactor:** don't export variable `s` by default anymore, it will be extracted by `register` function (**Breaking Change**) +- **meta:** add `categories` and `template` config to `typst.toml` for Typst 0.11 + + +## v0.3.1 + +- fix some typos +- fix slide-level bug +- fix bug of pdfpc label + + +## v0.3.0 + +### Features + +- better show-slides mode. +- support align and pad. + +### Documentation + +- Add more detailed documentation. + +### Refactor + +- simplify theme. + +### Fix + +- fix many bugs. + +## v0.2.1 + +### Features + +- **Touying-reducer**: support cetz and fletcher animation +- **university theme**: add university theme + +### Fix + +- fix footer progress in metropolis theme +- fix some bugs in simple and dewdrop themes +- fix bug that outline does not display more than 4 sections + + +## v0.2.0 + +- **Object-oriented programming:** Singleton `s`, binding methods `utils.methods(s)` and `(self: obj, ..) => {..}` methods. +- **Page arguments management:** Instead of using `#set page(..)`, you should use `self.page-args` to retrieve or set page parameters, thereby avoiding unnecessary creation of new pages. +- **`#pause` for sequence content:** You can use #pause at the outermost level of a slide, including inline and list. +- **`#pause` for layout functions:** You can use the `composer` parameter to add yourself layout function like `utils.side-by-side`, and simply use multiple pos parameters like `#slide[..][..]`. +- **`#meanwhile` for synchronous display:** Provide a `#meanwhile` for resetting subslides counter. +- **`#pause` and `#meanwhile` for math equation:** Provide a `#touying-equation("x + y pause + z")` for math equation animations. +- **Slides:** Create simple slides using standard headings. +- **Callback-style `uncover`, `only` and `alternatives`:** Based on the concise syntax provided by Polylux, allow precise control of the timing for displaying content. + - You should manually control the number of subslides using the `repeat` parameter. +- **Transparent cover:** Enable transparent cover using oop syntax like `#let s = (s.methods.enable-transparent-cover)(self: s)`. +- **Handout mode:** enable handout mode by `#let s = (s.methods.enable-handout-mode)(self: s)`. +- **Fit-to-width and fit-to-height:** Fit-to-width for title in header and fit-to-height for image. + - `utils.fit-to-width(grow: true, shrink: true, width, body)` + - `utils.fit-to-height(width: none, prescale-width: none, grow: true, shrink: true, height, body)` +- **Slides counter:** `states.slide-counter.display() + " / " + states.last-slide-number` and `states.touying-progress(ratio => ..)`. +- **Appendix:** Freeze the `last-slide-number` to prevent the slide number from increasing further. +- **Sections:** Touying's built-in section support can be used to display the current section title and show progress. + - `section` and `subsection` parameter in `#slide` to register a new section or subsection. + - `states.current-section-title` to get the current section. + - `states.touying-outline` or `s.methods.touying-outline` to display a outline of sections. + - `states.touying-final-sections(sections => ..)` for custom outline display. + - `states.touying-progress-with-sections((current-sections: .., final-sections: .., current-slide-number: .., last-slide-number: ..) => ..)` for powerful progress display. +- **Navigation bar**: Navigation bar like [here](https://github.com/zbowang/BeamerTheme) by `states.touying-progress-with-sections(..)`, in `dewdrop` theme. +- **Pdfpc:** pdfpc support and export `.pdfpc` file without external tool by `typst query` command simply. diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/code-styles.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/code-styles.md new file mode 100644 index 000000000..2b4a4d74c --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/code-styles.md @@ -0,0 +1,169 @@ +--- +sidebar_position: 4 +--- + +# 代码风格 + +## 简单风格 + +如果我们只是需要简单使用,我们可以直接在标题下输入内容,就像是在编写正常 Typst 文档一样。这里的标题有着分割页面的作用,同时我们也能正常地使用 `#pause` 等命令实现动画效果。 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register() +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/f5bdbf8f-7bf9-45fd-9923-0fa5d66450b2) + +并且你可以使用空标题 `==` 创建一个新页,这个技巧也有助于清除上一个标题的继续应用。 + +PS:我们可以使用 `#slides-end` 记号来标志 `#show: slides` 的结束。 + + +## 块风格 + +很多时候,仅仅使用简单风格并不能实现我们需要的所有功能,为了更强大的功能和更清晰的结构,我们同样可以使用 `#slide[...]` 形式的块风格,其中 `#slide` 函数需要使用 `#let (slide,) = utils.slides(s)` 语法进行解包,才能正常在 `#show: slides` 后使用。 + +例如上面的例子就可以改造成 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register() +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides + += Title + +== First Slide + +#slide[ + Hello, Touying! + + #pause + + Hello, Typst! +] +``` + +这样做的好处有很多: + +1. 很多时候,我们不只是需要默认的 `#slide[...]`,还需要 `#focus-slide[...]` 这些特殊的 `slide` 函数; +2. 不同主题的 `#slide[...]` 函数可能有比默认更多的参数,例如 university 主题的 `#slide[...]` 函数就会有着 `subtitle` 参数; +3. 只有 `slide` 函数才可以通过回调风格的内容块来使用 `#only` 和 `#uncover` 函数实现复杂的动画效果。 +4. 能有着更清晰的结构,通过辨别 `#slide[...]` 块,我们可以很容易地分辨出 slides 的具体分页效果。 + + +## 约定优于配置 + +你可能注意到了,在使用 simple 主题时,我们使用一级标题会自动创建一个 section slide,这是因为 simple 主题注册了一个 `s.methods.touying-new-section-slide` 方法,因此 touying 会默认调用这个方法。 + +如果我们不希望它自动创建这样一个 section slide,我们可以将这个方法删除: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register() +#(s.methods.touying-new-section-slide = none) +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/17a89a59-9491-4e1f-95c0-09a22105ab35) + +如你所见,这样就只会剩下两页,而默认的 section slide 就会消失了。 + +同理,我们也可以注册一个新的 section slide: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register() +#(s.methods.touying-new-section-slide = (self: none, section, ..args) => { + self = utils.empty-page(self) + (s.methods.touying-slide)(self: self, section: section, { + set align(center + horizon) + set text(size: 2em, fill: s.colors.primary, style: "italic", weight: "bold") + section + }, ..args) +}) +#let (init, slides, touying-outline) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/5305efda-0cd4-42eb-9f2e-89abc30b6ca2) + +同样地,我们也可以修改 `s.methods.touying-new-subsection-slide` 来对 `subsection` 做同样的事。 + +实际上,除了 `s.methods.touying-new-section-slide`,另一个特殊的 `slide` 函数就是 `s.methods.slide` 函数,它会在简单风格里没有显示使用 `#slide[...]` 的情况下默认被调用。 + +同时,由于 `#slide[...]` 被注册在了 `s.slides = ("slide",)` 里,因此 `section`,`subsection` 和 `title` 参数会被自动传入,而其他的如 `#focus-slide[...]` 则不会自动传入这三个参数。 + +:::tip[原理] + +实际上,你也可以不使用 `#show: slides` 和 `utils.slides(s)`,而是只使用 `utils.methods(s)`,例如 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register() +#let (init, touying-outline, slide) = utils.methods(s) +#show: init + +#slide(section: [Title], title: [First Slide])[ + Hello, Touying! + + #pause + + Hello, Typst! +] +``` + +这时候需要手动传入 `section`、`subsection` 和 `title`,但是会有更好的性能,适合需要更快的性能的情况,例如超过数十数百页的情形。 + +::: \ No newline at end of file diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/_category_.json b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/_category_.json new file mode 100644 index 000000000..f4d0e7caf --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "动态幻灯片", + "position": 7, + "link": { + "type": "generated-index", + "description": "想要在 PDF 中创建动画,我们就需要为同一个 slide 创建多个略有不同的页面,以便通过切换页面的方式实现动画,我们称这些页面为 subslides。" + } +} diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/complex.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/complex.md new file mode 100644 index 000000000..7a9abaa7a --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/complex.md @@ -0,0 +1,82 @@ +--- +sidebar_position: 2 +--- + +# 复杂动画 + +得益于 [Polylux](https://polylux.dev/book/dynamic/syntax.html) 提供的语法,我们同样能够在 Touying 中使用 `only`、`uncover` 和 `alternatives`。 + + +## 回调风格的函数 + +为了避免上文提到的 `styled` 与 `layout` 限制,Touying 利用回调函数巧妙实现了总是能生效的 `only`、`uncover` 和 `alternatives`,具体来说,您要这样引入这三个函数: + +```typst +#slide(repeat: 3, self => [ + #let (uncover, only, alternatives) = utils.methods(self) + + In subslide #self.subslide, + + test #uncover("2-")[uncover] function, + + and test #only("2-")[only] function, + + #pause + + and paused text. +]) +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/e9a6b8c5-daf0-4cf2-8d39-1a768ce1dfea) + +注意到了吗?我们不再是传入一个内容块,而是传入了一个参数为 `self` 的回调函数,随后我们通过 + +```typst +#let (uncover, only, alternatives) = utils.methods(self) +``` + +从 `self` 中取出了 `only`、`uncover` 和 `alternatives` 这三个函数,并在后续调用它们。 + +这里还有一些有趣的事实,例如 int 类型的 `self.subslide` 指示了当前 subslide 索引,而实际上 `only`、`uncover` 和 `alternatives` 函数也正是依赖 `self.subslide` 实现的获取当前 subslide 索引。 + +:::warning[警告] + +我们手动指定了参数 `repeat: 3`,这代表着显示 3 张 subslides,我们需要手动指定是因为 Touying 无法探知 `only`、`uncover` 和 `alternatives` 需要显示多少张 subslides。 + +::: + +## only + +`only` 函数表示只在选定的 subslides 中「出现」,如果不出现,则会完全消失,也不会占据任何空间。也即 `#only(index, body)` 要么为 `body` 要么为 `none`。 + +其中 index 可以是 int 类型,也可以是 `"2-"` 或 `"2-3"` 这样的 str 类型,更多用法可以参考 [Polylux](https://polylux.dev/book/dynamic/complex.html)。 + + +## uncover + +`uncover` 函数表示只在选定的 subslides 中「显示」,否则会被 `cover` 函数遮挡,但仍会占据原有。也即 `#uncover(index, body)` 要么为 `body` 要么为 `cover(body)`。 + +其中 index 可以是 int 类型,也可以是 `"2-"` 或 `"2-3"` 这样的 str 类型,更多用法可以参考 [Polylux](https://polylux.dev/book/dynamic/complex.html)。 + +您应该也注意到了,事实上 `#pause` 也使用了 `cover` 函数,只是提供了更便利的写法,实际上它们的效果基本上是一致的。 + + +## alternatives + +`alternatives` 函数表示在不同的 subslides 中展示一系列不同的内容,例如 + +```typst +#slide(repeat: 3, self => [ + #let (uncover, only, alternatives) = utils.methods(self) + + #alternatives[Ann][Bob][Christopher] + likes + #alternatives[chocolate][strawberry][vanilla] + ice cream. +]) +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/392707ea-0bcd-426b-b232-5bc63b9a13a3) + +如你所见,`alternatives` 能够自动撑开到最合适的宽度和高度,这是 `only` 和 `uncover` 所没有的能力。事实上 `alternatives` 还有着其他参数,例如 `start: 2`、`repeat-last: true` 和 `position: center + horizon` 等,更多用法可以参考 [Polylux](https://polylux.dev/book/dynamic/alternatives.html)。 + diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/cover.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/cover.md new file mode 100644 index 000000000..a188b0e77 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/cover.md @@ -0,0 +1,72 @@ +--- +sidebar_position: 4 +--- + +# Cover 函数 + +正如您已经了解的那样,`uncover` 和 `#pause` 均会使用 `cover` 函数对不显示的内容进行遮盖。那么,这里的 `cover` 函数究竟是什么呢? + + +## 默认 Cover 函数:`hide` + +`cover` 函数是保存在 `s.methods.cover` 的一个方法,后续 `uncover` 和 `#pause` 均会在这里取出 `cover` 函数来使用。 + +默认的 `cover` 函数是 [hide](https://typst.app/docs/reference/layout/hide/) 函数,这个函数能将内部的内容更改为不可见的,且不会影响布局。 + + +## 更新 Cover 函数 + +有的情况下,您想用您自己的 `cover` 函数,那么您可以通过 + +```typst +let s = (s.methods.update-cover)(self: s, is-method: true, cover-fn) +``` + +方法来设置您自己的 `cover` 函数,其中如果设置 `is-method: false`,则 Touying 会帮您将 `cover-fn` 包装成一个方法。 + + +## 半透明 Cover 函数 + +Touying 提供了半透明 Cover 函数的支持,只需要加入 + +```typst +#let s = (s.methods.enable-transparent-cover)(self: s) +``` + +即可开启,其中你可以通过 `alpha: ..` 参数调节透明度。 + + +:::warning[警告] + +注意,这里的 `transparent-cover` 并不能像 `hide` 一样不影响文本布局,因为里面有一层 `box`,因此可能会破坏页面原有的结构。 + +::: + + +:::tip[原理] + +`enable-transparent-cover` 方法定义为 + +```typst +#let s.methods.enable-transparent-cover = ( + self: none, + constructor: rgb, + alpha: 85%, +) => { + self.methods.cover = (self: none, body) => { + utils.cover-with-rect( + fill: utils.update-alpha( + constructor: constructor, + self.page-args.fill, + alpha, + ), + body + ) + } + self +} +``` + +可以看出,其是通过 `utils.cover-with-rect` 创建了一个与背景色同色的半透明矩形遮罩,以模拟内容透明的效果,其中 `constructor: rgb` 和 `alpha: 85%` 分别表明了背景色的构造函数与透明程度。 + +::: \ No newline at end of file diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/equation.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/equation.md new file mode 100644 index 000000000..b28429613 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/equation.md @@ -0,0 +1,71 @@ +--- +sidebar_position: 3 +--- + +# 数学公式动画 + +Touying 还提供了一个独特且十分有用的功能,即数学公式动画,它让你可以方便地在数学公式里使用 `pause` 和 `meanwhile`。 + +## 简单动画 + +让我们先来看一个例子: + +```typst +#slide[ + Touying equation with pause: + + #touying-equation(` + f(x) &= pause x^2 + 2x + 1 \ + &= pause (x + 1)^2 \ + `) + + #meanwhile + + Touying equation is very simple. +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/d176e61f-c0da-4c2a-a1bf-52621be5adb2) + + +我们使用 `touying-equation` 函数来实现在数学公式文本内部使用 `pause` 和 `meanwhile`(事实上,你也能用 `#pause` 或者 `#pause;`)。 + +正如你料想的一样,数学公式会分步显示,这很适合给让演讲者演示自己的数学公式推理思路。 + +:::warning[警告] + +虽然 `touying-equation` 函数很便利,但是您需要时刻注意,`touying-equation` 并不会做复杂的语法分析,只是单纯地正则表达式分割字符串,因此您不应在 `display(..)` 这类函数内部使用 `pause` 或 `meanwhile`! + +::: + + +## 复杂动画 + +事实上,我们也可以在 `touying-equation` 内部使用 `only`、`uncover` 和 `alternatives`,只是需要一点技巧: + +```typst +#slide(repeat: 3, self => [ + #let (uncover, only, alternatives) = utils.methods(self) + + #touying-equation(scope: (uncover: uncover), ` + f(x) &= pause x^2 + 2x + uncover("3-", 1) \ + &= pause (x + 1)^2 \ + `) +]) +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/f2df14a2-6424-4c53-81f7-1595aa330660) + + +我们可以在 `touying-equation` 的 `scope` 参数中将我们需要用到的函数传递进去,例如这里的 `uncover`。 + + +## 参数 + +`touying-equation` 的函数定义为 + +```typst +#let touying-equation(block: true, numbering: none, supplement: auto, scope: (:), body) = { .. } +``` + +因此,我们可以像使用普通数学公式一样,为 `touying-equation` 传入 `block`、`numbering` 和 `supplement` 参数。 \ No newline at end of file diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/handout.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/handout.md new file mode 100644 index 000000000..c6120e8db --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/handout.md @@ -0,0 +1,15 @@ +--- +sidebar_position: 6 +--- + +# 创建讲义 + +在看幻灯片、听课的同时,听众往往会希望有一个讲义,以便能够回顾理解困难的地方,所以,作者最好能给听众提供这样一份讲义,如果能在听课前提供更好。 + +讲义模式与普通模式的区别是,其不需要过于繁杂的动画效果,因此只会保留每个 slide 的最后一张 subslide。 + +开启讲义模式是很简单的: + +```typst +#let s = (s.methods.enable-handout-mode)(self: s) +``` diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/other.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/other.md new file mode 100644 index 000000000..4dffa801f --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/other.md @@ -0,0 +1,100 @@ +--- +sidebar_position: 5 +--- + +# 其他动画 + +Touying 还提供了 `touying-reducer`,它能为 cetz 与 fletcher 加入 `pause` 和 `meanwhile` 动画。 + +## 简单动画 + +一个例子: + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/cetz:0.2.1" +#import "@preview/fletcher:0.4.2" as fletcher: node, edge + +#let cetz-canvas = touying-reducer.with(reduce: cetz.canvas, cover: cetz.draw.hide.with(bounds: true)) +#let fletcher-diagram = touying-reducer.with(reduce: (arr, ..args) => fletcher.diagram(..args, ..arr)) + +#let s = themes.metropolis.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides.with(title-slide: false, outline-slide: false) + +// cetz animation +#slide[ + Cetz in Touying: + + #cetz-canvas({ + import cetz.draw: * + + rect((0,0), (5,5)) + + (pause,) + + rect((0,0), (1,1)) + rect((1,1), (2,2)) + rect((2,2), (3,3)) + + (pause,) + + line((0,0), (2.5, 2.5), name: "line") + }) +] + +// fletcher animation +#slide[ + Fletcher in Touying: + + #fletcher-diagram( + node-stroke: .1em, + node-fill: gradient.radial(blue.lighten(80%), blue, center: (30%, 20%), radius: 80%), + spacing: 4em, + edge((-1,0), "r", "-|>", `open(path)`, label-pos: 0, label-side: center), + node((0,0), `reading`, radius: 2em), + edge((0,0), (0,0), `read()`, "--|>", bend: 130deg), + pause, + edge(`read()`, "-|>"), + node((1,0), `eof`, radius: 2em), + pause, + edge(`close()`, "-|>"), + node((2,0), `closed`, radius: 2em, extrude: (-2.5, 0)), + edge((0,0), (2,0), `close()`, "-|>", bend: -40deg), + ) +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/9ba71f54-2a5d-4144-996c-4a42833cc5cc) + + +## only 与 uncover + +事实上,我们也可以在 cetz 内部使用 `only` 和 `uncover`,只是需要一点技巧: + +```typst +#slide(repeat: 3, self => [ + #let (uncover, only) = utils.methods(self) + + Cetz in Touying in subslide #self.subslide: + + #cetz.canvas({ + import cetz.draw: * + let self = (self.methods.update-cover)(self: self, hide) + let (uncover,) = utils.methods(self) + + rect((0,0), (5,5)) + + uncover("2-3", { + rect((0,0), (1,1)) + rect((1,1), (2,2)) + rect((2,2), (3,3)) + }) + + only(3, line((0,0), (2.5, 2.5), name: "line")) + }) +]) +``` \ No newline at end of file diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/simple.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/simple.md new file mode 100644 index 000000000..ec3c3ae20 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/dynamic/simple.md @@ -0,0 +1,86 @@ +--- +sidebar_position: 1 +--- + +# 简单动画 + +Touying 为简单的动画效果提供了两个标记:`#pause` 和 `#meanwhile`。 + +## pause + +`#pause` 的用途很简单,就是用于将后续的内容放到下一张 subslide 中,并且可以使用多个 `#pause` 以创建多张 subslides,一个简单的例子: + +```typst +#slide[ + First #pause Second + + #pause + + Third +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/a3bed1d3-e660-456d-8a54-a914436f43bf) + +这个例子将会创建三张 subslides,逐渐地将内容展示出来。 + +如你所见,`#pause` 既可以放在行内,也可以放在单独的一行。 + + +## meanwhile + +有些情况下,我们需要在 `#pause` 的同时展示一些其他内容,这时候我们就可以用 `#meanwhile`。 + +```typst +#slide[ + First + + #pause + + Second + + #meanwhile + + Third + + #pause + + Fourth +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/24ca19a3-b27c-4d31-ab75-09c37911e6ac) + +这个例子只会创建两张 subslides,并且 "First" 和 "Third" 同时显示,"Second" 和 "Fourth" 同时显示。 + + +## 如何处理 set-show rules? + +如果你在 `slide[..]` 里面使用了 set-show rules,你会惊讶的发现,在那之后的 `#pause` 和 `#meanwhile` 都失效了。这是因为 Touying 无法探知 `styled(..)` 内部的内容(set-show rules 后的内容会被 `styled` 囊括起来)。 + +为了解决这个问题,Touying 为 `#slide()` 函数提供了一个 `setting` 参数,你可以将你的 set-show rules 放到 `setting` 参数里,例如修改字体颜色: + +```typst +#slide(setting: body => { + set text(fill: blue) + body +})[ + First + + #pause + + Second +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/8e31fc8a-5ab1-4181-a46a-fa96cf790dff) + + +同理,Touying 目前也不支持 `grid` 这类 layout 函数内部的 `#pause` 和 `#meanwhile`,也是由于同样的限制,但是你可以使用 `#slide()` 的 `composer` 参数,大部分情况下都应该能满足需求。 + + +:::tip[原理] + +Touying 不依赖 `counter` 和 `locate` 来实现 `#pause`,而是用 Typst 脚本写了一个 parser。它会将输入内容块作为 sequence 解析,然后改造重组这个 sequence 为我们需要的一系列 subslides。 + +::: \ No newline at end of file diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/external/_category_.json b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/external/_category_.json new file mode 100644 index 000000000..3e273e04f --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/external/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "外部工具", + "position": 13, + "link": { + "type": "generated-index", + "description": "使用外部工具与 Touying 集成。" + } +} diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/external/pdfpc.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/external/pdfpc.md new file mode 100644 index 000000000..d0d44d011 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/external/pdfpc.md @@ -0,0 +1,60 @@ +--- +sidebar_position: 1 +--- + +# pdfpc + +[pdfpc](https://pdfpc.github.io/) 是一个 "对 PDF 文档具有多显示器支持的演示者控制台"。这意味着,您可以使用它以 PDF 页面的形式显示幻灯片,并且还具有一些已知的出色功能,就像 PowerPoint 一样。 + +pdfpc 有一个 JSON 格式的 `.pdfpc` 文件,它可以为 PDF slides 提供更多的信息。虽然您可以手动编写此它,但你也可以通过 Touying 来管理。 + + +## 加入 Metadata + +Touying 与 [Polylux](https://polylux.dev/book/external/pdfpc.html) 保持一致,以避免 API 之间的冲突。 + +例如,你可以通过 `#pdfpc.speaker-note("This is a note that only the speaker will see.")` 加入 notes。 + + +## pdfpc 配置 + +为了加入 pdfpc 配置,你可以使用 + +```typst +#let s = (s.methods.append-preamble)(self: s, pdfpc.config( + duration-minutes: 30, + start-time: datetime(hour: 14, minute: 10, second: 0), + end-time: datetime(hour: 14, minute: 40, second: 0), + last-minutes: 5, + note-font-size: 12, + disable-markdown: false, + default-transition: ( + type: "push", + duration-seconds: 2, + angle: ltr, + alignment: "vertical", + direction: "inward", + ), +)) +``` + +加入对应的配置,具体配置方法可以参考 [Polylux](https://polylux.dev/book/external/pdfpc.html)。 + + +## 输出 .pdfpc 文件 + +假设你的文档为 `./example.typ`,则你可以通过 + +```sh +typst query --root . ./example.typ --field value --one "" > ./example.pdfpc +``` + +直接导出 `.pdfpc` 文件。 + +借助 Touying 与 Polylux 的兼容性,你可以让 Polylux 也支持直接导出,只需要加入下面的代码即可。 + +``` +#import "@preview/touying:0.3.2" + +#locate(loc => touying.pdfpc.pdfpc-file(loc)) +``` \ No newline at end of file diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/external/typst-preview.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/external/typst-preview.md new file mode 100644 index 000000000..9934eb5ea --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/external/typst-preview.md @@ -0,0 +1,15 @@ +--- +sidebar_position: 2 +--- + +# Typst Preview + +VS Code 的 Typst Preview 插件提供了优秀的 slide mode,我们可以用其预览和放映 slides。 + +按下 `Ctrl/Cmd + Shift + P`,并输入 `Typst Preview: Preview current file in slide mode`,就可以打开 slide mode 的预览。 + +按下 `Ctrl/Cmd + Shift + P`,并输入 `Typst Preview: Preview current file in browser and slide mode`,就可以在浏览器打开 slide mode。 + +这时候你可以按下 `F11` 之类的键,进入浏览器的全屏模式,就可以用于 slides 放映了。 + +由于 Typst Preview 是基于 SVG 的,因此可以播放 GIF 动图,这对于动态 slides 很有帮助。 diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/global-settings.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/global-settings.md new file mode 100644 index 000000000..bc668049c --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/global-settings.md @@ -0,0 +1,170 @@ +--- +sidebar_position: 6 +--- + +# 全局设置 + +## 全局样式 + +对 Touying 而言,全局样式即为需要应用到所有地方的 set rules 或 show rules,例如 `#set text(size: 20pt)`。 + +其中,Touying 的主题会封装一些自己的全局样式,他们会被放在 `#show: init` 中,例如 university 主题就封装了 + +```typst +self.methods.init = (self: none, body) => { + set text(size: 25pt) + show footnote.entry: set text(size: .6em) + body +} +``` + +如果你并非一个主题制作者,而只是想给你的 slides 添加一些自己的全局样式,你可以简单地将它们放在 `#show: init` 之后,以及 `#show: slides` 之前,例如 metropolis 主题就推荐你自行加入以下全局样式: + +```typst +#let s = themes.metropolis.register(aspect-ratio: "16-9") +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +// global styles +#set text(font: "Fira Sans", weight: "light", size: 20pt) +#show math.equation: set text(font: "Fira Math") +#set strong(delta: 100) +#set par(justify: true) +#show strong: alert + +#let (slide, title-slide, new-section-slide, focus-slide) = utils.slides(s) +#show: slides +``` + +但是注意,你不应该使用 `#set page(..)`,而是应该修改 `s.page-args` 和 `s.padding`,例如 + +```typst +#(s.page-args += ( + margin: (x: 0em, y: 2em), + header: align(top)[Header], + footer: align(bottom)[Footer], + header-ascent: 0em, + footer-descent: 0em, +)) +#(s.padding += (x: 4em, y: 0em)) +``` + + +## 全局信息 + +就像 Beamer 一样,Touying 通过 OOP 风格的统一 API 设计,能够帮助您更好地维护全局信息,让您可以方便地在不同的主题之间切换,全局信息就是一个很典型的例子。 + +你可以通过 + +```typst +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +``` + +分别设置 slides 的标题、副标题、作者、日期和机构信息。在后续,你就可以通过 `s.info` 或 `self.info` 这样的方式访问它们。 + +这些信息一般会在主题的 `title-slide`、`header` 和 `footer` 被使用到,例如 `#let s = themes.metropolis.register(aspect-ratio: "16-9", footer: self => self.info.institution)`。 + +其中 `date` 可以接收 `datetime` 格式和 `content` 格式,并且 `datetime` 格式的日期显示格式,可以通过 + +```typst +#let s = (s.methods.datetime-format)(self: s, "[year]-[month]-[day]") +``` + +的方式更改。 + +:::tip[原理] + +在这里,我们会稍微引入一点 Touying 的 OOP 概念。 + +您应该知道,Typst 是一个支持增量渲染的排版语言,也就是说,Typst 会缓存之前的函数调用结果,这就要求 Typst 里只有纯函数,即无法改变外部变量的函数。因此我们很难真正意义上地像 LaTeX 那样修改一个全局变量。即使是使用 `state` 或 `counter`,也需要使用 `locate` 与回调函数来获取里面的值,且实际上这种方式会对性能有很大的影响。 + +Touying 并没有使用 `state` 和 `counter`,也没有违反 Typst 纯函数的原则,而是使用了一种巧妙的方式,并以面向对象风格的代码,维护了一个全局单例 `s`。在 Touying 中,一个对象指拥有自己的成员变量和方法的 Typst 字典,并且我们约定方法均有一个命名参数 `self` 用于传入对象自身,并且方法均放在 `.methods` 域里。有了这个理念,我们就不难写出更新 `info` 的方法了: + +``` +#let s = ( + info: (:), + methods: ( + // update info + info: (self: none, ..args) => { + self.info += args.named() + self + }, + ) +) + +#let s = (s.methods.info)(self: s, title: [title]) + +Title is #s.info.title +``` + +这样,你也能够理解 `utils.methods()` 函数的用途了:将 `self` 绑定到 `s` 的所有方法上并返回,并通过解包语法简化后续的使用。 + +```typst +#let (init, slides, alert) = utils.methods(s) +``` +::: + + +## 状态初始化 + +一般而言,上面的两种方式就已经足够用于加入全局设置了,但是仍然会有部分情况,我们需要初始化 counters 或 states。如果将这些代码放在 `#show: slides` 之前,就会创建一个空白页,这是我们不想看见的,因此这时候我们就可以使用 `s.methods.append-preamble` 方法。例如在使用 codly 包的时候: + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/codly:0.2.0": * + +#let s = themes.simple.register(aspect-ratio: "16-9") +#let s = (s.methods.append-preamble)(self: s)[ + #codly(languages: ( + rust: (name: "Rust", icon: "\u{fa53}", color: rgb("#CE412B")), + )) +] +#let (init, slides) = utils.methods(s) +#show heading.where(level: 2): set block(below: 1em) +#show: init +#show: codly-init.with() + +#let (slide,) = utils.slides(s) +#show: slides + +#slide[ + == First slide + + #raw(lang: "rust", block: true, +`pub fn main() { + println!("Hello, world!"); +}`.text) +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/0be2fbaf-cc03-4776-932f-259503d5e23a) + + +又或者是进行 Pdfpc 的配置的时候: + +```typst +// Pdfpc configuration +// typst query --root . ./example.typ --field value --one "" > ./example.pdfpc +#let s = (s.methods.append-preamble)(self: s, pdfpc.config( + duration-minutes: 30, + start-time: datetime(hour: 14, minute: 10, second: 0), + end-time: datetime(hour: 14, minute: 40, second: 0), + last-minutes: 5, + note-font-size: 12, + disable-markdown: false, + default-transition: ( + type: "push", + duration-seconds: 2, + angle: ltr, + alignment: "vertical", + direction: "inward", + ), +)) +``` \ No newline at end of file diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/_category_.json b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/_category_.json new file mode 100644 index 000000000..8a6bf0ea2 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "第三方包集成", + "position": 8, + "link": { + "type": "generated-index", + "description": "让第三方包与 Touying 集成。" + } +} diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/cetz.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/cetz.md new file mode 100644 index 000000000..c1fc6fc97 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/cetz.md @@ -0,0 +1,100 @@ +--- +sidebar_position: 3 +--- + +# CeTZ + +Touying 提供了 `touying-reducer`,它能为 cetz 与 fletcher 加入 `pause` 和 `meanwhile` 动画。 + +## 简单动画 + +一个例子: + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/cetz:0.2.1" +#import "@preview/fletcher:0.4.2" as fletcher: node, edge + +#let cetz-canvas = touying-reducer.with(reduce: cetz.canvas, cover: cetz.draw.hide.with(bounds: true)) +#let fletcher-diagram = touying-reducer.with(reduce: (arr, ..args) => fletcher.diagram(..args, ..arr)) + +#let s = themes.metropolis.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides.with(title-slide: false, outline-slide: false) + +// cetz animation +#slide[ + Cetz in Touying: + + #cetz-canvas({ + import cetz.draw: * + + rect((0,0), (5,5)) + + (pause,) + + rect((0,0), (1,1)) + rect((1,1), (2,2)) + rect((2,2), (3,3)) + + (pause,) + + line((0,0), (2.5, 2.5), name: "line") + }) +] + +// fletcher animation +#slide[ + Fletcher in Touying: + + #fletcher-diagram( + node-stroke: .1em, + node-fill: gradient.radial(blue.lighten(80%), blue, center: (30%, 20%), radius: 80%), + spacing: 4em, + edge((-1,0), "r", "-|>", `open(path)`, label-pos: 0, label-side: center), + node((0,0), `reading`, radius: 2em), + edge((0,0), (0,0), `read()`, "--|>", bend: 130deg), + pause, + edge(`read()`, "-|>"), + node((1,0), `eof`, radius: 2em), + pause, + edge(`close()`, "-|>"), + node((2,0), `closed`, radius: 2em, extrude: (-2.5, 0)), + edge((0,0), (2,0), `close()`, "-|>", bend: -40deg), + ) +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/9ba71f54-2a5d-4144-996c-4a42833cc5cc) + + +## only 与 uncover + +事实上,我们也可以在 cetz 内部使用 `only` 和 `uncover`,只是需要一点技巧: + +```typst +#slide(repeat: 3, self => [ + #let (uncover, only) = utils.methods(self) + + Cetz in Touying in subslide #self.subslide: + + #cetz.canvas({ + import cetz.draw: * + let self = (self.methods.update-cover)(self: self, hide) + let (uncover,) = utils.methods(self) + + rect((0,0), (5,5)) + + uncover("2-3", { + rect((0,0), (1,1)) + rect((1,1), (2,2)) + rect((2,2), (3,3)) + }) + + only(3, line((0,0), (2.5, 2.5), name: "line")) + }) +]) +``` \ No newline at end of file diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/codly.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/codly.md new file mode 100644 index 000000000..a9de5c758 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/codly.md @@ -0,0 +1,37 @@ +--- +sidebar_position: 5 +--- + +# Codly + +在使用 codly 的时候,我们应该使用 `s.methods.append-preamble` 方法进行初始化。 + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/codly:0.2.0": * + +#let s = themes.simple.register(aspect-ratio: "16-9") +#let s = (s.methods.append-preamble)(self: s)[ + #codly(languages: ( + rust: (name: "Rust", icon: "\u{fa53}", color: rgb("#CE412B")), + )) +] +#let (init, slides) = utils.methods(s) +#show heading.where(level: 2): set block(below: 1em) +#show: init +#show: codly-init.with() + +#let (slide,) = utils.slides(s) +#show: slides + +#slide[ + == First slide + + #raw(lang: "rust", block: true, +`pub fn main() { + println!("Hello, world!"); +}`.text) +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/0be2fbaf-cc03-4776-932f-259503d5e23a) diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/fletcher.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/fletcher.md new file mode 100644 index 000000000..7c455d031 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/fletcher.md @@ -0,0 +1,69 @@ +--- +sidebar_position: 4 +--- + +# Fletcher + +Touying 提供了 `touying-reducer`,它能为 fletcher 加入 `pause` 和 `meanwhile` 动画。 + +一个例子: + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/cetz:0.2.1" +#import "@preview/fletcher:0.4.2" as fletcher: node, edge + +#let cetz-canvas = touying-reducer.with(reduce: cetz.canvas, cover: cetz.draw.hide.with(bounds: true)) +#let fletcher-diagram = touying-reducer.with(reduce: (arr, ..args) => fletcher.diagram(..args, ..arr)) + +#let s = themes.metropolis.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides.with(title-slide: false, outline-slide: false) + +// cetz animation +#slide[ + Cetz in Touying: + + #cetz-canvas({ + import cetz.draw: * + + rect((0,0), (5,5)) + + (pause,) + + rect((0,0), (1,1)) + rect((1,1), (2,2)) + rect((2,2), (3,3)) + + (pause,) + + line((0,0), (2.5, 2.5), name: "line") + }) +] + +// fletcher animation +#slide[ + Fletcher in Touying: + + #fletcher-diagram( + node-stroke: .1em, + node-fill: gradient.radial(blue.lighten(80%), blue, center: (30%, 20%), radius: 80%), + spacing: 4em, + edge((-1,0), "r", "-|>", `open(path)`, label-pos: 0, label-side: center), + node((0,0), `reading`, radius: 2em), + edge((0,0), (0,0), `read()`, "--|>", bend: 130deg), + pause, + edge(`read()`, "-|>"), + node((1,0), `eof`, radius: 2em), + pause, + edge(`close()`, "-|>"), + node((2,0), `closed`, radius: 2em, extrude: (-2.5, 0)), + edge((0,0), (2,0), `close()`, "-|>", bend: -40deg), + ) +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/9ba71f54-2a5d-4144-996c-4a42833cc5cc) \ No newline at end of file diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/mitex.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/mitex.md new file mode 100644 index 000000000..8d576a46b --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/mitex.md @@ -0,0 +1,26 @@ +--- +sidebar_position: 2 +--- + +# MiTeX + +在创建 slides 的过程中,往往我们已经有了一个 LaTeX 数学公式,只是想贴到 slides 的里面,而不想把它转写成 Typst 数学公式,这时候我们就可以用 [MiTeX](https://github.com/mitex-rs/mitex) 了。 + +示例: + +```typst +#import "@preview/mitex:0.2.1": * + +Write inline equations like #mi("x") or #mi[y]. + +Also block equations (this case is from #text(blue.lighten(20%), link("https://katex.org/")[katex.org])): + +#mitex(` + \newcommand{\f}[2]{#1f(#2)} + \f\relax{x} = \int_{-\infty}^\infty + \f\hat\xi\,e^{2 \pi i \xi x} + \,d\xi +`) +``` + +![image](https://github.com/mitex-rs/mitex/assets/34951714/c425b2ae-b50b-46a8-a451-4d9e8e70626b) diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/pinit.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/pinit.md new file mode 100644 index 000000000..08589d2e1 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/pinit.md @@ -0,0 +1,124 @@ +--- +sidebar_position: 1 +--- + +# Pinit + +[Pinit](https://github.com/OrangeX4/typst-pinit/) 包其提供了一个基于页面绝对定位与基于「图钉」pins 相对定位的能力,可以很方便地为 slides 实现箭头指示与解释说明的效果。 + +## 简单示例 + +```typst +#import "@preview/pinit:0.1.3": * + +#set text(size: 24pt) + +A simple #pin(1)highlighted text#pin(2). + +#pinit-highlight(1, 2) + +#pinit-point-from(2)[It is simple.] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/b17f9b80-5a8b-4943-a222-bcb0eb38611d) + +另一个 [示例](https://github.com/OrangeX4/typst-pinit/blob/main/examples/equation-desc.typ): + +![image](https://github.com/touying-typ/touying/assets/34951714/9b4a6b50-fcfd-497d-9649-ae1f7762ee3f) + + + +## 复杂示例 + +![image](https://github.com/touying-typ/touying/assets/34951714/7fb0095a-fd86-49ec-af95-15bc81a341c2) + + +一个与 Touying 共同使用的示例: + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/pinit:0.1.3": * + +#(s.page-args.paper = "presentation-4-3") +#let (init, slides) = utils.methods(s) +#show: init + +#set text(size: 20pt, font: "Calibri", ligatures: false) +#show heading: set text(weight: "regular") +#show heading: set block(above: 1.4em, below: 1em) +#show heading.where(level: 1): set text(size: 1.5em) + +// Useful functions +#let crimson = rgb("#c00000") +#let greybox(..args, body) = rect(fill: luma(95%), stroke: 0.5pt, inset: 0pt, outset: 10pt, ..args, body) +#let redbold(body) = { + set text(fill: crimson, weight: "bold") + body +} +#let blueit(body) = { + set text(fill: blue) + body +} + +#let (slide,) = utils.slides(s) +#show: slides + +// Main body +#slide(self => [ + #let (uncover, only) = utils.methods(self) + + = Asymptotic Notation: $O$ + + Use #pin("h1")asymptotic notations#pin("h2") to describe asymptotic efficiency of algorithms. + (Ignore constant coefficients and lower-order terms.) + + #pause + + #greybox[ + Given a function $g(n)$, we denote by $O(g(n))$ the following *set of functions*: + #redbold(${f(n): "exists" c > 0 "and" n_0 > 0, "such that" f(n) <= c dot g(n) "for all" n >= n_0}$) + ] + + #pinit-highlight("h1", "h2") + + #pause + + $f(n) = O(g(n))$: #pin(1)$f(n)$ is *asymptotically smaller* than $g(n)$.#pin(2) + + // #absolute-place(dx: 550pt, dy: 320pt, image(width: 25%, "asymptotic.png")) + + #pause + + $f(n) redbold(in) O(g(n))$: $f(n)$ is *asymptotically* #redbold[at most] $g(n)$. + + #only("4-", pinit-line(stroke: 3pt + crimson, start-dy: -0.25em, end-dy: -0.25em, 1, 2)) + + #pause + + #block[Insertion Sort as an #pin("r1")example#pin("r2"):] + + - Best Case: $T(n) approx c n + c' n - c''$ #pin(3) + - Worst case: $T(n) approx c n + (c' \/ 2) n^2 - c''$ #pin(4) + + #pinit-rect("r1", "r2") + + #pause + + #pinit-place(3, dx: 15pt, dy: -15pt)[#redbold[$T(n) = O(n)$]] + #pinit-place(4, dx: 15pt, dy: -15pt)[#redbold[$T(n) = O(n)$]] + + #pause + + #blueit[Q: Is $n^(3) = O(n^2)$#pin("que")? How to prove your answer#pin("ans")?] + + #pause + + #only("8-", pinit-point-to("que", fill: crimson, redbold[No.])) + #only("8-", pinit-point-from("ans", body-dx: -150pt)[ + Show that the equation $(3/2)^n >= c$ \ + has infinitely many solutions for $n$. + ]) +]) +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/f36a026f-491c-4290-90d5-0aa3c2086567) diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/polylux.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/polylux.md new file mode 100644 index 000000000..9f316a308 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/integration/polylux.md @@ -0,0 +1,21 @@ +--- +sidebar_position: 6 +--- + +# Polylux + +借助 Touying 与 Polylux 的兼容性,你可以让 Polylux 也支持直接导出,只需要在你的 Polylux 源代码中加入下面的代码即可。 + +``` +#import "@preview/touying:0.3.2" + +#locate(loc => touying.pdfpc.pdfpc-file(loc)) +``` + +假设你的文档为 `./example.typ`,则你可以通过 + +```sh +typst query --root . ./example.typ --field value --one "" > ./example.pdfpc +``` + +直接导出 `.pdfpc` 文件,而不需要使用额外的 `polylux2pdfpc` 程序。 \ No newline at end of file diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/intro.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/intro.md new file mode 100644 index 000000000..e8fcf12c0 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/intro.md @@ -0,0 +1,42 @@ +--- +sidebar_position: 1 +--- + +# Touying 介绍 + +[Touying](https://github.com/touying-typ/touying) 是为 Typst 开发的幻灯片/演示文稿包。Touying 也类似于 LaTeX 的 Beamer,但是得益于 Typst,你可以拥有更快的渲染速度与更简洁的语法。后面,我们会使用 slides 指代幻灯片,slide 指代单张幻灯片,subslide 指代子幻灯片。 + +## 为什么使用 Touying + +- 相较于 PowerPoint,Touying 并非「所示即所得的」,你可以使用一种「内容与样式分离」的方式编写你的 slides,尤其是 Typst 作为一个新兴的排版语言,提供了简洁但强大的语法,对于代码块、数学公式和定理等内容有着更好的支持。另一个优势是,在有着模板的情况下,用 Touying 编写 slides 要比 PowerPoint 快得多。因此 Touying 相较于 PowerPoint,更适合有着「科研写作」需求的用户使用。 +- 相较于 Markdown Slides,Touying 所依托的 Typst 有着更强大的排版控制能力,例如页眉、页脚、布局和便捷的自定义函数,而这是 Markdown 很难具备、或者说很难做好的能力。并且 Touying 提供了 `#pause` 和 `#meanwhile` 标记,提供了更为便捷的动态 slides 能力。 +- 相较于 Beamer,Touying 有着更快的编译速度、更简洁的语法,以及更简单的自定义主题的能力。相较于 Beamer 动辄几秒几十秒的编译时间,Touying 的编译速度基本上能够维持在几毫秒几十毫秒。并且 Touying 的语法相较于 Beamer 更为简洁,也更容易更改模板主题,以及创建你自己的模板。在功能上,Touying 支持了 Beamer 大部分的能力,并且还提供了一些 Beamer 所没有的便利功能。 +- 相较于 Polylux,Touying 提供了一种 oop 风格的语法,能够通过全局单例模拟提供「全局变量」的能力,进而可以方便地编写主题。并且 Touying 并不依赖 `counter` 和 `locate` 来实现 `#pause`,因此能有更好的性能。Touying 自身定位是一个社区驱动的项目(我们欢迎更多的人加入),并且不会过分强调维持 API 的一致性,而是选择维护多个版本的文档,因而能够提供更多新颖但强大的功能。 + +## 名称来源 + +Touying 取自中文里的「投影」,在英文中意为 project。相较而言,LaTeX 中的 beamer 就是德文的投影仪的意思。 + +## 关于文档 + +这个文档通过 [Docusaurus](https://docusaurus.io/) 驱动开发,我们将会为 Touying 维持英文和中文版本的文档,并且每个大版本维护一份文档,以便你随时可以查阅旧版本的 Touying 文档,并且可以更容易地迁移到新版本。 + +Docusaurus 创建新版本: + +```sh +npm run docusaurus docs:version 0.y.x +``` + +Docusaurus 多语言: + +```sh +npm run start -- --locale zh +``` + +## 贡献 + +Touying 是免费、开源且社区驱动的。如果你感兴趣,你可以随时访问 [GitHub](https://github.com/touying-typ/touying) 并提出 issue 或 PR,我们也同样欢迎你加入 [touying-typ](https://github.com/touying-typ) 组织。 + +## License + +Touying is released under the [MIT license](https://github.com/touying-typ/touying/blob/main/LICENSE). \ No newline at end of file diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/layout.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/layout.md new file mode 100644 index 000000000..6d79bcb80 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/layout.md @@ -0,0 +1,181 @@ +--- +sidebar_position: 5 +--- + +# 页面布局 + +## 基础概念 + +要想使用 Typst 制作一个样式美观的 slides,正确理解 Typst 的页面模型是必须的,如果你不关心自定义页面样式,你可以选择跳过这部分,否则还是推荐看一遍这部分。 + +下面我们通过一个具体的例子来说明 Typst 的默认页面模型。 + +```typst +#let container = rect.with(height: 100%, width: 100%, inset: 0pt) +#let innerbox = rect.with(stroke: (dash: "dashed")) + +#set text(size: 30pt) +#set page( + paper: "presentation-16-9", + header: container[#innerbox[Header]], + header-ascent: 30%, + footer: container[#innerbox[Footer]], + footer-descent: 30%, +) +#let padding = (x: 2em, y: 2em) + +#place(top + right)[Margin→] +#container[ + #place[Padding] + #pad(..padding)[ + #container[ + #innerbox[Content] + ] + ] +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/6cbb1092-c733-41b6-a15d-822ce970ef13) + +我们需要区分以下概念: + +1. **Model:** Typst 拥有与 CSS Box Model 类似的模型,分为 Margin、Padding 和 Content,但其中 padding 并非 `set page(..)` 的属性,而是我们手动添加 `#pad(..)` 得到的。 +2. **Margin:** 页边距,分为上下左右四个方向,是 Typst 页面模型的核心,其他属性都会受到页边距的影响,尤其是 Header 和 Footer,其实际上是位于 Margin 内部。 +3. **Padding:** 用于在 Margin 和 Content 之间添加额外的间隙。 +4. **Header:** Header 是页面顶部的内容,又分为 container 和 innerbox。我们可以注意到 header container 和 padding 的边缘并不贴合,而是也有一定的空隙,这个空隙实际上就是 `header-ascent: 30%`,而这里的百分比是相对于 margin-top 而言的。并且,我们注意到 header innerbox 实际上位于 header container 左下角,也即 innerbox 实际上默认有属性 `#set align(left + bottom)`。 +5. **Footer:** Footer 是页面底部的内容,又分为 container 和 innerbox。我们可以注意到 footer container 和 padding 的边缘并不贴合,而是也有一定的空隙,这个空隙实际上就是 `footer-descent: 30%`,而这里的百分比是相对于 margin-bottom 而言的。并且,我们注意到 footer innerbox 实际上位于 footer container 左上角,也即 innerbox 实际上默认有属性 `#set align(left + top)`。 +6. **Place:** `place` 函数可以实现绝对定位,在不影响父容器内其他元素的情况下,相对于父容器来定位,并且可以传入 `alignment`、`dx` 和 `dy`,很适合用来放置一些修饰元素,例如 Logo 之类的图片。 + +因此,要将 Typst 应用到制作 slides 上,我们只需要设置 + +```typst +#set page( + margin: (x: 0em, y: 2em), + header: align(top)[Header], + footer: align(bottom)[Footer], + header-ascent: 0em, + footer-descent: 0em, +) +#let padding = (x: 4em, y: 0em) +``` + +即可。例如我们有 + +```typst +#let container = rect.with(stroke: (dash: "dashed"), height: 100%, width: 100%, inset: 0pt) +#let innerbox = rect.with(fill: rgb("#d0d0d0")) + +#set text(size: 30pt) +#set page( + paper: "presentation-16-9", + margin: (x: 0em, y: 2em), + header: container[#align(top)[#innerbox(width: 100%)[Header]]], + header-ascent: 0em, + footer: container[#align(bottom)[#innerbox(width: 100%)[Footer]]], + footer-descent: 0em, +) +#let padding = (x: 4em, y: 0em) + +#place(top + right)[↑Margin] +#container[ + #place[Padding] + #pad(..padding)[ + #container[ + #innerbox[Content] + ] + ] +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/6127d231-86f3-4262-b7c6-b199d47ae12b) + +## 页面管理 + +由于 Typst 中使用 `set page(..)` 命令来修改页面参数,会导致创建一个新的页面,而不能修改当前页面,因此 Touying 选择维护一个 `s.page-args` 成员变量和一个 `s.padding` 成员变量,只在 Touying 自己创建新 slide 时才会自己应用这些参数,因此用户只需要关注 `s.page-args` 和 `s.padding` 即可。 + +例如,上面的例子就可以改成 + +```typst +#(s.page-args += ( + margin: (x: 0em, y: 2em), + header: align(top)[Header], + footer: align(bottom)[Footer], + header-ascent: 0em, + footer-descent: 0em, +)) +#(s.padding += (x: 4em, y: 0em)) +``` + +同理,如果你对某个主题的 header 或 footer 样式不满意,你也可以通过 + +```typst +#(s.page-args.footer = [Custom Footer]) +``` + +这样方式进行更换。不过需要注意的是,如果这样更换了页面参数,你需要将其放在 `#let (slide,) = utils.slides(s)` 之前,否则就需要重新调用 `#let (slide,) = utils.slides(s)`。 + +:::warning[警告] + +因此,你不应该自己使用 `set page(..)` 命令,而是应该修改 `s` 内部的 `s.page-args` 成员变量。 + +::: + +借助这种方式,我们也可以通过 `s.page-args` 实时查询当前页面的参数,这对一些需要获取页边距或当前页面背景颜色的函数很有用,例如 `transparent-cover`。这里就部分等价于 context get rule,而且实际上用起来会更方便。 + +## 应用:添加 Logo + +为 slides 添加一个 Logo 是及其普遍,但是又及其多变的一个需求。其中的难点在于,所需要的 Logo 大小和位置往往因人而异。因此,Touying 的主题大部分都不包含 Logo 的配置选项。但借助本章节提到的页面布局的概念,我们知道可以在 header 或 footer 中使用 `place` 函数来放置 Logo 图片。 + +例如,我们决定给 metropolis 主题加入 GitHub 的图标,我们可以这样实现: + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/octique:0.1.0": * + +#let s = themes.metropolis.register(aspect-ratio: "16-9") +#(s.page-args.header = self => { + // display the original header + utils.call-or-display(self, s.page-args.header) + // place logo to top-right + place(top + right, dx: -0.5em, dy: 0.3em)[ + #octique("mark-github", color: rgb("#fafafa"), width: 1.5em, height: 1.5em) + ] +}) +#let (init, slide) = utils.methods(s) +#show: init + +#slide(title: [Title])[ + Logo example. +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/055d77e7-5087-4248-b969-d8ef9d50c54b) + +其中 `utils.call-or-display(self, body)` 可以用于显示 `body` 为 content 或 `body` 为形如 `self => content` 形式的回调函数。 + +## 页面分栏 + +如果你需要将页面分为两栏或三栏,你可以使用 Touying `slide` 函数默认提供的 `compose` 功能,最简单的示例如下: + +```typst +#slide[ + First column. +][ + Second column. +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/a39f88a2-f1ba-4420-8f78-6a0fc644704e) + +如果你需要更改分栏的方式,可以修改 `slide` 的 `composer` 参数,其中默认的参数是 `utils.with.side-by-side(columns: auto, gutter: 1em)`,如果我们要让左边那一栏占据剩余宽度,可以使用 + +```typst +#slide(composer: utils.side-by-side.with(columns: (1fr, auto), gutter: 1em))[ + First column. +][ + Second column. +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/aa84192a-4082-495d-9773-b06df32ab8dc) + diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/progress/_category_.json b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/progress/_category_.json new file mode 100644 index 000000000..04521b095 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/progress/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "进度", + "position": 11, + "link": { + "type": "generated-index", + "description": "管理和展示 Touying 中的进度,例如 counters 和 sections 等。" + } +} diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/progress/counters.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/progress/counters.md new file mode 100644 index 000000000..3ce28cf1f --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/progress/counters.md @@ -0,0 +1,48 @@ +--- +sidebar_position: 1 +--- + +# Touying 的计数器 + +Touying 的状态均放置于 `states` 命名空间下,包括所有的计数器。 + +## slide 计数器 + +你可以通过 `states.slide-counter` 获取 slide 计数器,并且通过 `states.slide-counter.display()` 展示当前 slide 的序号。 + + +## last-slide 计数器 + +因为有些情形下,我们需要为 slides 加入后记,因此就有了冻结 last-slide 计数器的需求,因此这里维护了第二个计数器。 + +我们可以使用 `states.last-slide-number` 展示后记前最后一张 slide 的序号。 + + +## 进度 + +我们可以使用 + +```typst +#states.touying-progress(ratio => ..) +``` + +来显示当前的进度。 + + +## 后记 + +你可以使用 + +```typst +// appendix by freezing last-slide-number +#let s = (s.methods.appendix)(self: s) +#let (slide,) = utils.methods(s) + +#slide[ + appendix +] +``` + +语法进入后记。 + +并且 `#let s = (s.methods.appendix-in-outline)(self: s, false)` 可以让后记的 section 不显示在大纲中。 \ No newline at end of file diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/progress/sections.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/progress/sections.md new file mode 100644 index 000000000..1fe859ba8 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/progress/sections.md @@ -0,0 +1,25 @@ +--- +sidebar_position: 2 +--- + +# Touying 的 Sections + +Touying 维护了一份自己的 sections state,用于记录 slides 的 sections 和 subsections。 + +## touying-outline + +`#touying-outline(enum-args: (:), padding: 0pt)` 用于显示一个简单的大纲。 + + +## touying-final-sections + +`#states.touying-final-sections(final-sections => ..)` 用于自定义显示大纲。 + + +## touying-progress-with-sections + +```typst +#states.touying-progress-with-sections((current-sections: .., final-sections: .., current-slide-number: .., last-slide-number: ..) => ..) +``` + +功能最强大,你可以用其搭建任意复杂的进度展示。 diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/sections.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/sections.md new file mode 100644 index 000000000..1eb03fcae --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/sections.md @@ -0,0 +1,98 @@ +--- +sidebar_position: 3 +--- + +# 节与小节 + +## 结构 + +与 Beamer 相同,Touying 同样有着 section 和 subsection 的概念。 + +一般而言,1 级、2 级和 3 级标题分别用来对应 section、subsection 和 title,例如 dewdrop 主题。 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.dewdrop.register() +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides + += Section + +== Subsection + +=== Title + +Hello, Touying! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/1574e74d-25c1-418f-a84f-b974f42edae5) + +但是很多时候我们并不需要 subsection,因此也会使用 1 级和 2 级标题来分别对应 section 和 title,例如 university 主题。 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.university.register() +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides + += Section + +== Title + +Hello, Touying! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/9dd77c98-9c08-4811-872e-092bbdebf394) + +实际上,我们可以通过 `slides` 函数的 `slide-level` 参数来控制这里的行为。`slide-level` 代表着嵌套结构的复杂度,从 0 开始计算。例如 `#show: slides.with(slide-level: 2)` 等价于 `section`,`subsection` 和 `title` 结构;而 `#show: slides.with(slide-level: 1)` 等价于 `section` 和 `title` 结构。 + + +## 目录 + +在 Touying 中显示目录很简单: + +```typst +#import "@preview/touying:0.3.2": * + +#let (init, slides, alert, touying-outline) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides.with(slide-level: 2) + += Section + +== Subsection + +=== Title + +==== Table of contents + +#touying-outline() +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/3cc09550-d3cc-40c2-a315-22ca8173798f) + +其中 `touying-oultine()` 的定义为: + +```typst +#let touying-outline(enum-args: (:), padding: 0pt) = { .. } +``` + +你可以通过 `enum-args` 修改内部 enum 的参数。 + +如果你对目录有着复杂的自定义需求,你可以使用 + +```typst +#states.touying-final-sections(sections => ..) +``` + +正如 dewdrop 主题所做的那样。 \ No newline at end of file diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/start.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/start.md new file mode 100644 index 000000000..518c0b9ca --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/start.md @@ -0,0 +1,241 @@ +--- +sidebar_position: 2 +--- + +# 开始 + +在开始之前,请确保您已经安装了 Typst 环境,如果没有,可以使用 [Web App](https://typst.app/) 或 VS Code 的 [Typst LSP](https://marketplace.visualstudio.com/items?itemName=nvarner.typst-lsp) 和 [Typst Preview](https://marketplace.visualstudio.com/items?itemName=mgt19937.typst-preview) 插件。 + +要使用 Touying,您只需要在文档里加入 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register() +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/f5bdbf8f-7bf9-45fd-9923-0fa5d66450b2) + +这很简单,您创建了您的第一个 Touying slides,恭喜!🎉 + +**提示:** 你可以使用 `#import "config.typ": *` 或 `#include "content.typ"` 等 Typst 语法来实现 Touying 的多文件架构。 + +**警告:** `#let (slide,) = utils.slides(s)` 里的逗号对于解包语法来说是必要的! + +## 更复杂的例子 + +事实上,Touying 提供了多种 slides 编写风格,实际上您也可以使用 `#slide[..]` 的写法,以获得 Touying 提供的更多更强大的功能。 + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/cetz:0.2.1" +#import "@preview/fletcher:0.4.2" as fletcher: node, edge + +// cetz and fletcher bindings for touying +#let cetz-canvas = touying-reducer.with(reduce: cetz.canvas, cover: cetz.draw.hide.with(bounds: true)) +#let fletcher-diagram = touying-reducer.with(reduce: (arr, ..args) => fletcher.diagram(..args, ..arr)) + +// Register university theme +// You can remove the theme registration or replace other themes +// it can still work normally +#let s = themes.university.register(aspect-ratio: "16-9") + +// Global information configuration +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) + +// Pdfpc configuration +// typst query --root . ./example.typ --field value --one "" > ./example.pdfpc +#let s = (s.methods.append-preamble)(self: s, pdfpc.config( + duration-minutes: 30, + start-time: datetime(hour: 14, minute: 10, second: 0), + end-time: datetime(hour: 14, minute: 40, second: 0), + last-minutes: 5, + note-font-size: 12, + disable-markdown: false, + default-transition: ( + type: "push", + duration-seconds: 2, + angle: ltr, + alignment: "vertical", + direction: "inward", + ), +)) + +// Extract methods +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +// Extract slide functions +#let (slide,) = utils.slides(s) +#show: slides + += Animation + +== Simple Animation + +#slide[ + 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. +] + + +== Complex Animation + +#slide(repeat: 3, self => [ + #let (uncover, only, alternatives) = utils.methods(self) + + At subslide #self.subslide, we can + + use #uncover("2-")[`#uncover` function] for reserving space, + + use #only("2-")[`#only` function] for not reserving space, + + #alternatives[call `#only` multiple times \u{2717}][use `#alternatives` function #sym.checkmark] for choosing one of the alternatives. +]) + + +== Math Equation Animation + +#slide[ + Touying equation with `pause`: + + #touying-equation(` + f(x) &= pause x^2 + 2x + 1 \ + &= pause (x + 1)^2 \ + `) + + #meanwhile + + Here, #pause we have the expression of $f(x)$. + + #pause + + By factorizing, we can obtain this result. +] + + +== CeTZ Animation + +#slide[ + CeTZ Animation in Touying: + + #cetz-canvas({ + import cetz.draw: * + + rect((0,0), (5,5)) + + (pause,) + + rect((0,0), (1,1)) + rect((1,1), (2,2)) + rect((2,2), (3,3)) + + (pause,) + + line((0,0), (2.5, 2.5), name: "line") + }) +] + + +== Fletcher Animation + +#slide[ + Fletcher Animation in Touying: + + #fletcher-diagram( + node-stroke: .1em, + node-fill: gradient.radial(blue.lighten(80%), blue, center: (30%, 20%), radius: 80%), + spacing: 4em, + edge((-1,0), "r", "-|>", `open(path)`, label-pos: 0, label-side: center), + node((0,0), `reading`, radius: 2em), + edge((0,0), (0,0), `read()`, "--|>", bend: 130deg), + pause, + edge(`read()`, "-|>"), + node((1,0), `eof`, radius: 2em), + pause, + edge(`close()`, "-|>"), + node((2,0), `closed`, radius: 2em, extrude: (-2.5, 0)), + edge((0,0), (2,0), `close()`, "-|>", bend: -40deg), + ) +] + + += Others + +== Side-by-side + +#slide[ + First column. +][ + Second column. +] + + +== Setting + +#slide(setting: body => { + set text(fill: blue) + body +})[ + This slide has blue text. +] + + +== Multiple Pages + +#slide[ + #lorem(200) +] + + +// appendix by freezing last-slide-number +#let s = (s.methods.appendix)(self: s) +#let (slide,) = utils.slides(s) + +== Appendix + +#slide[ + Please pay attention to the current slide number. +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/fcecb505-d2d1-4e36-945a-225f4661a694) + +Touying 提供了很多内置的主题,能够简单地编写精美的 slides,例如此处的 + +``` +#let s = themes.university.register(aspect-ratio: "16-9") +``` + +可以使用 university 主题。关于主题更详细的教程,您可以参阅后面的章节。 diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/_category_.json b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/_category_.json new file mode 100644 index 000000000..e397dffcd --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "主题", + "position": 9, + "link": { + "type": "generated-index", + "description": "使用 Touying 很便利的一点就是,你可以使用 Touying 提供的主题,或者是借助 Touying 创建自己的主题或模板。" + } +} diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/aqua.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/aqua.md new file mode 100644 index 000000000..f67661b78 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/aqua.md @@ -0,0 +1,201 @@ +--- +sidebar_position: 5 +--- + +# Aqua 主题 + +![image](https://github.com/touying-typ/touying/assets/34951714/5f9b3c99-a22a-4f3d-a266-93dd75997593) + +这个主题由 [@pride7](https://github.com/pride7) 制作,它的美丽背景为使用 Typst 的可视化功能制作的矢量图形。 + + +## 初始化 + +你可以通过下面的代码来初始化: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.aqua.register(aspect-ratio: "16-9", lang: "en") +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, outline-slide, focus-slide) = utils.slides(s) +#show: slides +``` + +其中 `register` 接收参数: + +- `aspect-ratio`: 幻灯片的长宽比为 "16-9" 或 "4-3",默认为 "16-9"。 +- `footer`: 展示在页脚右侧的内容,默认为 `states.slide-counter.display()`。 +- `lang`: 语言配置,目前只支持 `"en"` 和 `"zh"`,默认为 `"en"`, + +并且 Aqua 主题会提供一个 `#alert[..]` 函数,你可以通过 `#show strong: alert` 来使用 `*alert text*` 语法。 + +## 颜色主题 + +Aqua 默认使用了 + +```typst +#let s = (s.methods.colors)( + self: s, + primary: rgb("#003F88"), + primary-light: rgb("#2159A5"), + primary-lightest: rgb("#F2F4F8"), +``` + +颜色主题,你可以通过 `#let s = (s.methods.colors)(self: s, ..)` 对其进行修改。 + +## slide 函数族 + +Aqua 主题提供了一系列自定义 slide 函数: + +```typst +#title-slide(..args) +``` + +`title-slide` 会读取 `self.info` 里的信息用于显示。 + +--- + +```typst +#let outline-slide(self: none, enum-args: (:), leading: 50pt) +``` + +显示一个大纲页。 + +--- + +```typst +#slide( + repeat: auto, + setting: body => body, + composer: utils.side-by-side, + section: none, + subsection: none, + // Aqua theme + title: auto, +)[ + ... +] +``` +默认拥有标题和页脚的普通 slide 函数,其中 `title` 默认为当前 section title。 + +--- + +```typst +#focus-slide[ + ... +] +``` +用于引起观众的注意力。背景色为 `self.colors.primary`。 + +--- + +```typst +#new-section-slide(title) +``` +用给定标题开启一个新的 section。 + + +## `slides` 函数 + +`slides` 函数拥有参数 + +- `title-slide`: 默认为 `true`。 +- `outline-slide`: 默认为 `true`。 +- `slide-level`: 默认为 `1`。 + +可以通过 `#show: slides.with(..)` 的方式设置。 + +PS: 其中 outline title 可以通过 `#(s.outline-title = [Outline])` 的方式修改。 + +以及可以通过 `#(s.methods.touying-new-section-slide = none)` 的方式关闭自动加入 `new-section-slide` 的功能。 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.aqua.register(aspect-ratio: "16-9", lang: "en") +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, outline-slide, focus-slide) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/eea4df8d-d9fd-43ac-aaf7-bb459864a9ac) + + + +## 示例 + +```typst +#import "../lib.typ": * + +#let s = themes.aqua.register(aspect-ratio: "16-9", lang: "en") +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, outline-slide, focus-slide) = utils.slides(s) +#show: slides + += The Section + +== Slide Title + +#slide[ + #lorem(40) +] + +#focus-slide[ + Another variant with primary color in background... +] + +== Summary + +#align(center + horizon)[ + #set text(size: 3em, weight: "bold", s.colors.primary) + THANKS FOR ALL +] +``` + diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/dewdrop.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/dewdrop.md new file mode 100644 index 000000000..62b1a201e --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/dewdrop.md @@ -0,0 +1,269 @@ +--- +sidebar_position: 3 +--- + +# Dewdrop 主题 + +![image](https://github.com/touying-typ/touying/assets/34951714/0b5b2bb2-c6ec-45c0-9cea-0af2ed896bba) + +这个主题的灵感来自 Zhibo Wang 创作的 [BeamerTheme](https://github.com/zbowang/BeamerTheme),由 [OrangeX4](https://github.com/OrangeX4) 改造而来。 + +这个主题拥有优雅美观的 navigation,包括 `sidebar` 和 `mini-slides` 两种模式。 + +## 初始化 + +你可以通过下面的代码来初始化: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.dewdrop.register( + aspect-ratio: "16-9", + footer: [Dewdrop], + navigation: "mini-slides", + // navigation: "sidebar", + // navigation: none, +) +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, new-section-slide, focus-slide) = utils.slides(s) +#show: slides +``` + +其中 `register` 接收参数: + +- `aspect-ratio`: 幻灯片的长宽比为 "16-9" 或 "4-3",默认为 "16-9"。 +- `navigation`: 导航栏样式,可以是 `"sidebar"`、`"mini-slides"` 和 `none`,默认为 `"sidebar"`。 +- `sidebar`: 侧边导航栏设置,默认为 `(width: 10em)`。 +- `mini-slides`: mini-slides 设置,默认为 `(height: 2em, x: 2em, section: false, subsection: true)`。 + - `height`: mini-slides 高度,默认为 `2em`。 + - `x`: mini-slides 的 x 轴 padding,默认为 `2em`。 + - `section`: 是否显示 section 之后,subsection 之前的 slides,默认为 `false`。 + - `subsection`: 是否根据 subsection 分割 mini-slides,设置为 `false` 挤压为一行,默认为 `true`。 +- `footer`: 展示在页脚的内容,默认为 `[]`,也可以传入形如 `self => self.info.author` 的函数。 +- `footer-right`: 展示在页脚右侧的内容,默认为 `states.slide-counter.display() + " / " + states.last-slide-number`。 +- `primary`: primary 颜色,默认为 `rgb("#0c4842")`。 +- `alpha`: 透明度,默认为 `70%`。 + +并且 Dewdrop 主题会提供一个 `#alert[..]` 函数,你可以通过 `#show strong: alert` 来使用 `*alert text*` 语法。 + +## 颜色主题 + +Dewdrop 默认使用了 + +```typst +#let s = (s.methods.colors)( + self: s, + neutral-darkest: rgb("#000000"), + neutral-dark: rgb("#202020"), + neutral-light: rgb("#f3f3f3"), + neutral-lightest: rgb("#ffffff"), + primary: primary, +) +``` + +颜色主题,你可以通过 `#let s = (s.methods.colors)(self: s, ..)` 对其进行修改。 + +## slide 函数族 + +Dewdrop 主题提供了一系列自定义 slide 函数: + +```typst +#title-slide(extra: none, ..args) +``` + +`title-slide` 会读取 `self.info` 里的信息用于显示,你也可以为其传入 `extra` 参数,显示额外的信息。 + +--- + +```typst +#slide( + repeat: auto, + setting: body => body, + composer: utils.side-by-side, + section: none, + subsection: none, + // Dewdrop theme + footer: auto, +)[ + ... +] +``` +默认拥有导航栏和页脚的普通 slide 函数,页脚为您设置的页脚。 + +--- + +```typst +#focus-slide[ + ... +] +``` +用于引起观众的注意力。背景色为 `self.colors.primary`。 + + +## 特殊函数 + +```typst +#d-outline(enum-args: (:), list-args: (:), cover: true) +``` + +显示当前的目录,`cover` 参数用于指定是否要隐藏处于 inactive 状态的 sections。 + +--- + +```typst +#d-sidebar() +``` + +内部函数,用于显示侧边栏。 + +--- + +```typst +#d-mini-slides() +``` + +内部函数,用于显示 mini-slides。 + + +## `slides` 函数 + +`slides` 函数拥有参数 + +- `title-slide`: 默认为 `true`。 +- `outline-slide`: 默认为 `true`。 +- `slide-level`: 默认为 `2`。 + +可以通过 `#show: slides.with(..)` 的方式设置。 + +PS: 其中 outline title 可以通过 `#(s.outline-title = [Outline])` 的方式修改。 + +以及可以通过 `#(s.methods.touying-new-section-slide = none)` 的方式关闭自动加入 `new-section-slide` 的功能。 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.dewdrop.register(aspect-ratio: "16-9", footer: [Dewdrop]) +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, new-section-slide, focus-slide) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/09ddfb40-4f97-4062-8261-23f87690c33e) + + +## 示例 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.dewdrop.register( + aspect-ratio: "16-9", + footer: [Dewdrop], + navigation: "mini-slides", + // navigation: none, +) +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, new-section-slide, focus-slide) = utils.slides(s) +#show: slides + += Section A + +== Subsection A.1 + +#slide[ + A slide with equation: + + $ x_(n+1) = (x_n + a/x_n) / 2 $ +] + +== Subsection A.2 + +#slide[ + A slide without a title but with *important* infos +] + += Section B + +== Subsection B.1 + +#slide[ + #lorem(80) +] + +#focus-slide[ + Wake up! +] + +== Subsection B.2 + +#slide[ + 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. +] + +// appendix by freezing last-slide-number +#let s = (s.methods.appendix)(self: s) +#let (slide,) = utils.slides(s) + += Appendix + +=== Appendix + +#slide[ + Please pay attention to the current slide number. +] +``` + diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/metropolis.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/metropolis.md new file mode 100644 index 000000000..af8f553a8 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/metropolis.md @@ -0,0 +1,228 @@ +--- +sidebar_position: 2 +--- + +# Metropolis 主题 + +![image](https://github.com/touying-typ/touying/assets/34951714/383ceb22-f696-4450-83a6-c0f17e4597e1) + + +这个主题的灵感来自 Matthias Vogelgesang 创作的 [Metropolis beamer](https://github.com/matze/mtheme) 主题,由 [Enivex](https://github.com/Enivex) 改造而来。 + +这个主题美观大方,很适合日常使用,并且你最好在电脑上安装 Fira Sans 和 Fira Math 字体,以取得最佳效果。 + + +## 初始化 + +你可以通过下面的代码来初始化: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.metropolis.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, new-section-slide, focus-slide) = utils.slides(s) +#show: slides +``` + +其中 `register` 接收参数: + +- `aspect-ratio`: 幻灯片的长宽比为 "16-9" 或 "4-3",默认为 "16-9"。 +- `header`: 显示在页眉的内容,默认为 `states.current-section-title`,也可以传入形如 `self => self.info.title` 的函数。 +- `footer`: 展示在页脚的内容,默认为 `[]`,也可以传入形如 `self => self.info.author` 的函数。 +- `footer-right`: 展示在页脚右侧的内容,默认为 `states.slide-counter.display() + " / " + states.last-slide-number`。 +- `footer-progress`: 是否显示 slide 底部的进度条,默认为 `true`。 + +并且 Metropolis 主题会提供一个 `#alert[..]` 函数,你可以通过 `#show strong: alert` 来使用 `*alert text*` 语法。 + +## 颜色主题 + +Metropolis 默认使用了 + +```typst +#let s = (s.methods.colors)( + self: s, + neutral-lightest: rgb("#fafafa"), + primary-dark: rgb("#23373b"), + secondary-light: rgb("#eb811b"), + secondary-lighter: rgb("#d6c6b7"), +) +``` + +颜色主题,你可以通过 `#let s = (s.methods.colors)(self: s, ..)` 对其进行修改。 + +## slide 函数族 + +Metropolis 主题提供了一系列自定义 slide 函数: + +```typst +#title-slide(extra: none, ..args) +``` + +`title-slide` 会读取 `self.info` 里的信息用于显示,你也可以为其传入 `extra` 参数,显示额外的信息。 + +--- + +```typst +#slide( + repeat: auto, + setting: body => body, + composer: utils.side-by-side, + section: none, + subsection: none, + // metropolis theme + title: auto, + footer: auto, + align: horizon, +)[ + ... +] +``` +默认拥有标题和页脚的普通 slide 函数,其中 `title` 默认为当前 section title,页脚为您设置的页脚。 + +--- + +```typst +#focus-slide[ + ... +] +``` +用于引起观众的注意力。背景色为 `self.colors.primary-dark`。 + +--- + +```typst +#new-section-slide(short-title: auto, title) +``` +用给定标题开启一个新的 section。 + + +## `slides` 函数 + +`slides` 函数拥有参数 + +- `title-slide`: 默认为 `true`。 +- `outline-slide`: 默认为 `true`。 +- `slide-level`: 默认为 `1`。 + +可以通过 `#show: slides.with(..)` 的方式设置。 + +PS: 其中 outline title 可以通过 `#(s.outline-title = [Outline])` 的方式修改。 + +以及可以通过 `#(s.methods.touying-new-section-slide = none)` 的方式关闭自动加入 `new-section-slide` 的功能。 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.metropolis.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let s = (s.methods.enable-transparent-cover)(self: s) +#let (init, slide, slides, title-slide, new-section-slide, focus-slide, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/4ab45ee6-09f7-498b-b349-e889d6e42e3e) + + +## 示例 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.metropolis.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#set text(font: "Fira Sans", weight: "light", size: 20pt) +#show math.equation: set text(font: "Fira Math") +#set strong(delta: 100) +#set par(justify: true) +#show strong: alert + +#let (slide, title-slide, new-section-slide, focus-slide) = utils.slides(s) +#show: slides + += First Section + +#slide[ + A slide without a title but with some *important* information. +] + +== A long long long long long long long long long long long long long long long long long long long long long long long long Title + +#slide[ + A slide with equation: + + $ x_(n+1) = (x_n + a/x_n) / 2 $ + + #lorem(200) +] + += Second Section + +#focus-slide[ + Wake up! +] + +== Simple Animation + +#slide[ + A simple #pause dynamic slide with #alert[alert] + + #pause + + text. +] + +// appendix by freezing last-slide-number +#let s = (s.methods.appendix)(self: s) +#let (slide,) = utils.slides(s) + += Appendix + +#slide[ + Appendix. +] +``` + diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/simple.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/simple.md new file mode 100644 index 000000000..3664be472 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/simple.md @@ -0,0 +1,170 @@ +--- +sidebar_position: 1 +--- + +# Simple 主题 + +![image](https://github.com/touying-typ/touying/assets/34951714/83d5295e-f961-4ffd-bc56-a7049848d408) + +这个主题来源于 [Polylux](https://polylux.dev/book/themes/gallery/simple.html),作者是 Andreas Kröpelin。 + +这个主题被认为是一个相对简单的主题,你可以用它来创建一个简单 slides,并且可以随意加入你喜欢的功能。 + + +## 初始化 + +你可以通过下面的代码来初始化: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register(aspect-ratio: "16-9", footer: [Simple slides]) +#let s = (s.methods.enable-transparent-cover)(self: s) +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide, title-slide, centered-slide, focus-slide) = utils.slides(s) +#show: slides +``` + +其中 `register` 接收参数: + +- `aspect-ratio`: 幻灯片的长宽比为 "16-9" 或 "4-3",默认为 "16-9"。 +- `footer`: 展示在页脚的内容,默认为 `[]`,也可以传入形如 `self => self.info.author` 的函数。 +- `footer-right`: 展示在页脚右侧的内容,默认为 `states.slide-counter.display() + " / " + states.last-slide-number`。 +- `background`: 背景颜色,默认为白色。 +- `foreground`: 文本颜色,默认为黑色。 +- `primary`: 主题颜色,默认为 `aqua.darken(50%)`。 + + +## slide 函数族 + +simple 主题提供了一系列自定义 slide 函数: + +```typst +#centered-slide(section: ..)[ + ... +] +``` +内容位于幻灯片中央的幻灯片,`section` 参数可以用于新建一个 section。 + +--- + +```typst +#title-slide[ + ... +] +``` + +和 `centered-slide` 相同,这里只是为了保持和 Polylux 语法上的一致性。 + +--- + +```typst +#slide( + repeat: auto, + setting: body => body, + composer: utils.side-by-side, + section: none, + subsection: none, + // simple theme args + footer: auto, +)[ + ... +] +``` +默认拥有页眉和页脚的普通 slide 函数,其中页眉为当前 section,页脚为您设置的页脚。 + +--- + +```typst +#focus-slide(foreground: ..., background: ...)[ + ... +] +``` +用于引起观众的注意力。可选接受一个前景色 (默认为 `white`) 和一个背景色 (默认为 `auto`,即 `self.colors.primary`)。 + + +## `slides` 函数 + +`slides` 函数拥有参数 + +- `slide-level`: 默认为 `1`。 + +可以通过 `#show: slides.with(..)` 的方式设置。 + +以及可以通过 `#(s.methods.touying-new-section-slide = none)` 的方式关闭自动加入 `new-section-slide` 的功能。 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register(aspect-ratio: "16-9", footer: [Simple slides]) +#let s = (s.methods.enable-transparent-cover)(self: s) +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide, title-slide, centered-slide, focus-slide) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/2c599bd1-6250-497f-a65b-f19ae02a16cb) + + +## 示例 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register(aspect-ratio: "16-9", footer: [Simple slides]) +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide, title-slide, centered-slide, focus-slide) = utils.slides(s) +#show: slides + +#title-slide[ + = Keep it simple! + #v(2em) + + Alpha #footnote[Uni Augsburg] #h(1em) + Bravo #footnote[Uni Bayreuth] #h(1em) + Charlie #footnote[Uni Chemnitz] #h(1em) + + July 23 +] + +== First slide + +#slide[ + #lorem(20) +] + +#focus-slide[ + _Focus!_ + + This is very important. +] + += Let's start a new section! + +== Dynamic slide + +#slide[ + Did you know that... + + #pause + + ...you can see the current section at the top of the slide? +] +``` + diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/university.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/university.md new file mode 100644 index 000000000..3ceb16895 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/themes/university.md @@ -0,0 +1,225 @@ +--- +sidebar_position: 4 +--- + +# University 主题 + +![image](https://github.com/touying-typ/touying/assets/34951714/4095163c-0c16-4760-b370-8adc1cdd7e6c) + +这个美观的主题来自 [Pol Dellaiera](https://github.com/drupol)。 + +## 初始化 + +你可以通过下面的代码来初始化: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.university.register(aspect-ratio: "16-9") +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#let (slide, title-slide, focus-slide, matrix-slide) = utils.slides(s) +#show: slides +``` + +其中 `register` 接收参数: + +- `aspect-ratio`: 幻灯片的长宽比为 "16-9" 或 "4-3",默认为 "16-9"。 +- `progress-bar`: 是否显示 slide 顶部的进度条,默认为 `true`。 +- `footer-columns`: 底部三栏 Footer 的宽度,默认为 `(25%, 1fr, 25%)`。 +- `footer-a`: 第一栏,默认为 `self => self.info.author`。 +- `footer-b`: 第二栏,默认为 `self => if self.info.short-title == auto { self.info.title } else { self.info.short-title }`。 +- `footer-c`: 第三栏,默认为 + +```typst +self => { + h(1fr) + utils.info-date(self) + h(1fr) + states.slide-counter.display() + " / " + states.last-slide-number + h(1fr) +} +``` + +并且 University 主题会提供一个 `#alert[..]` 函数,你可以通过 `#show strong: alert` 来使用 `*alert text*` 语法。 + +## 颜色主题 + +University 默认使用了 + +```typst +#let s = (s.methods.colors)( + self: s, + primary: rgb("#04364A"), + secondary: rgb("#176B87"), + tertiary: rgb("#448C95"), +) +``` + +颜色主题,你可以通过 `#let s = (s.methods.colors)(self: s, ..)` 对其进行修改。 + +## slide 函数族 + +University 主题提供了一系列自定义 slide 函数: + +```typst +#title-slide(logo: none, authors: none, ..args) +``` + +`title-slide` 会读取 `self.info` 里的信息用于显示,你也可以为其传入 `logo` 参数和 array 类型的 `authors` 参数。 + +--- + +```typst +#slide( + repeat: auto, + setting: body => body, + composer: utils.side-by-side, + section: none, + subsection: none, + // university theme + title: none, + subtitle: none, + header: none, + footer: auto, +)[ + ... +] +``` +默认拥有标题和页脚的普通 slide 函数,其中 `title` 默认为当前 section title,页脚为您设置的页脚。 + +--- + +```typst +#focus-slide(background-img: ..., background-color: ...)[ + ... +] +``` +用于引起观众的注意力。默认背景色为 `self.colors.primary`。 + +--- + +```typst +#new-section-slide(short-title: auto, title) +``` +用给定标题开启一个新的 section。 + +--- + +```typst +#matrix-slide(columns: ..., rows: ...)[ + ... +][ + ... +] +``` +可以参考 [文档](https://polylux.dev/book/themes/gallery/university.html)。 + + +## `slides` 函数 + +`slides` 函数拥有参数 + +- `title-slide`: 默认为 `true`。 +- `slide-level`: 默认为 `1`。 + +可以通过 `#show: slides.with(..)` 的方式设置。 + +以及可以通过 `#(s.methods.touying-new-section-slide = none)` 的方式关闭自动加入 `new-section-slide` 的功能。 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.university.register(aspect-ratio: "16-9") +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#let (slide, title-slide, focus-slide, matrix-slide) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/58971045-0b0d-46cb-acc2-caf766c2432d) + + +## 示例 + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.university.register(aspect-ratio: "16-9") +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#let (slide, title-slide, focus-slide, matrix-slide) = utils.slides(s) +#show: slides.with(title-slide: false) + +#title-slide(authors: ([Author A], [Author B])) + += The Section + +== Slide Title + +#slide[ + #lorem(40) +] + +#slide(subtitle: emph[What is the problem?])[ + #lorem(40) +] + +#focus-slide[ + *Another variant with primary color in background...* +] + +#matrix-slide[ + left +][ + middle +][ + right +] + +#matrix-slide(columns: 1)[ + top +][ + bottom +] + +#matrix-slide(columns: (1fr, 2fr, 1fr), ..(lorem(8),) * 9) +``` + diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/utilities/_category_.json b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/utilities/_category_.json new file mode 100644 index 000000000..293cae28c --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/utilities/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "工具", + "position": 12, + "link": { + "type": "generated-index", + "description": "一些便利的工具函数。" + } +} diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/utilities/fit-to.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/utilities/fit-to.md new file mode 100644 index 000000000..632b34664 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/utilities/fit-to.md @@ -0,0 +1,55 @@ +--- +sidebar_position: 2 +--- + +# Fit to height / width + +感谢 [ntjess](https://github.com/ntjess) 的代码。 + +## Fit to height + +如果你需要将图片占满剩余的 slide 高度,你可以来试试 `fit-to-height` 函数: + +```typst +#utils.fit-to-height(1fr)[BIG] +``` + +函数定义: + +```typst +#let fit-to-height( + width: none, prescale-width: none, grow: true, shrink: true, height, body +) = { .. } +``` + +参数: + +- `width`: 如果指定,这将确定缩放后内容的宽度。因此,如果您希望缩放的内容填充幻灯片宽度的一半,则可以使用 `width: 50%`。 +- `prescale-width`: 此参数允许您使 Typst 的布局假设给定的内容在缩放之前要布局在一定宽度的容器中。例如,您可以使用 `prescale-width: 200%` 假设幻灯片的宽度为原来的两倍。 +- `grow`: 是否可扩张,默认为 `true`。 +- `shrink`: 是否可收缩,默认为 `true`。 +- `height`: 需要指定的高度。 +- `body`: 具体的内容。 + + +## Fit to width + +如果你需要限制标题宽度刚好占满 slide 的宽度,你可以来试试 `fit-to-width` 函数: + +```typst +#utils.fit-to-width(1fr)[#lorem(20)] +``` + +函数定义: + +```typst +#let fit-to-width(grow: true, shrink: true, width, body) = { .. } +``` + +参数: + +- `grow`: 是否可扩张,默认为 `true`。 +- `shrink`: 是否可收缩,默认为 `true`。 +- `width`: 需要指定的宽度。 +- `body`: 具体的内容。 + diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/utilities/oop.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/utilities/oop.md new file mode 100644 index 000000000..42b311e58 --- /dev/null +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-0.3.2+/utilities/oop.md @@ -0,0 +1,28 @@ +--- +sidebar_position: 1 +--- + +# 面向对象编程 + +Touying 提供了一些便利的工具函数,便于进行面向对象编程。 + +--- + +```typst +#let call-or-display(self, it) = { + if type(it) == function { + return it(self) + } else { + return it + } +} +``` +调用或原样输出。 + +--- + +```typst +#let methods(self) = { .. } +``` +用于为方法绑定 self 并返回,十分常用。 + diff --git a/docs/versioned_docs/version-0.3.2+/build-your-own-theme.md b/docs/versioned_docs/version-0.3.2+/build-your-own-theme.md new file mode 100644 index 000000000..de2b6a586 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/build-your-own-theme.md @@ -0,0 +1,427 @@ +--- +sidebar_position: 10 +--- + +# Creating Your Own Theme + +Creating your own theme with Touying might seem a bit complex initially due to the introduction of various concepts. However, fear not; if you successfully create a custom theme with Touying, you'll likely experience the convenience and powerful customization features it offers. You can refer to the [source code of existing themes](https://github.com/touying-typ/touying/tree/main/themes) for guidance. The key steps to implement are: + +- Customize the `register` function to initialize the global singleton `s`. +- Customize the `init` method. +- Define a color theme by modifying the `self.colors` member variable. +- Customize the `alert` method (optional). +- Customize the header. +- Customize the footer. +- Customize the `slide` method. +- Customize special slide methods, such as `title-slide` and `focus-slide`. +- Customize the `slides` method (optional). + +To demonstrate creating a simple and elegant Bamboo theme, let's follow the steps. + +## Import + +Depending on whether the theme is for personal use or part of Touying, you can import in two ways: + +If for personal use: + +```typst +#import "@preview/touying:0.3.2": * +``` + +If part of Touying themes: + +```typst +#import "../utils/utils.typ" +#import "../utils/states.typ" +#import "../utils/components.typ" +``` + +Additionally, add the import statement in Touying's `themes/themes.typ`: + +``` +#import "bamboo.typ" +``` + + +## Register Function and Init Method + +Next, we'll distinguish between the bamboo.typ template file and the main.typ file, the latter of which is sometimes omitted. + +Generally, the first step in creating slides is to determine font size and page aspect ratio. Therefore, we need to register an initialization method: + +```typst +// bamboo.typ +#import "@preview/touying:0.3.2": * + +#let register( + self: themes.default.register(), + aspect-ratio: "16-9", +) = { + self.page-args += ( + paper: "presentation-" + aspect-ratio, + ) + self.methods.init = (self: none, body) => { + set text(size: 20pt) + body + } + self +} + +// main.typ +#import "@preview/touying:0.3.2": * +#import "bamboo.typ" + +#let s = bamboo.register(aspect-ratio: "16-9") +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide,) = utils.slides(s) +#show: slides + += First Section + +== First Slide + +#slide[ + A slide with a title and an *important* information. +] +``` + +As you can see, we created a `register` function and passed an `aspect-ratio` parameter to set the page aspect ratio. We get default `self` by `self: themes.default.register()`. As you might already know, in Touying, we should not use `set page(..)` to set page parameters but rather use the syntax `self.page-args += (..)` to set them, as explained in the Page Layout section. + +In addition, we registered a `self.methods.init` method, which can be used for some global style settings. For example, in this case, we added `set text(size: 20pt)` to set the font size. You can also place additional global style settings here, such as `set par(justify: true)`. Since the `init` function is placed inside `self.methods`, it is a method, not a regular function. Therefore, we need to add the parameter `self: none` to use it properly. + +As you can see, later in `main.typ`, we apply the global style settings in `init` using `#show: init`, where `init` is bound and unpacked through `utils.methods(s)`. + +If you pay extra attention, you'll notice that the `register` function has an independent `self` at the end. This actually represents returning the modified `self` as the return value, which will be saved in `#let s = ..`. This line is therefore indispensable. + +## Color Theme + +Choosing an attractive color theme for your slides is crucial. Touying provides built-in color theme support to minimize API differences between different themes. Touying offers two dimensions of color selection: the first is `neutral`, `primary`, `secondary`, and `tertiary` for hue distinction, with `primary` being the most commonly used; the second is `default`, `light`, `lighter`, `lightest`, `dark`, `darker`, and `darkest` for brightness distinction. + +As we are creating the Bamboo theme, we chose a color for the `primary` theme, similar to bamboo (`rgb("#5E8B65")`), and included neutral lightest/darkest as background and font colors. + +As shown in the code below, we use `(self.methods.colors)(self: self, ..)` to modify the color theme. Essentially, it is a wrapper for `self.colors += (..)`. + +```typst +#let register( + self: themes.default.register(), + aspect-ratio: "16-9", +) = { + // color theme + self = (self.methods.colors)( + self: self, + primary: rgb("#5E8B65"), + neutral-lightest: rgb("#ffffff"), + neutral-darkest: rgb("#000000"), + ) + self.page-args += ( + paper: "presentation-" + aspect-ratio, + ) + self.methods.init = (self: none, body) => { + set text(size: 20pt) + body + } + self +} +``` + +After adding the color theme, we can access the color using syntax like `self.colors.primary`. + +It's worth noting that users can change the theme color at any time using: + +```typst +#let s = (s.methods.colors)(self: s, primary: rgb("#3578B9")) +``` + +This flexibility demonstrates Touying's powerful customization capabilities. + +## Practical: Custom Alert Method + +In general, we need to provide a `#alert[..]` function for users, similar to `#strong[..]`. Typically, `#alert[..]` emphasizes text using the primary theme color for aesthetics. We add a line in the `register` function: + +```typst +self.methods.alert = (self: none, it) => text(fill: self.colors.primary, it) +``` + +This code sets the text color to `self.colors.primary`, utilizing the theme's primary color. + +## Custom Header and Footer + +Here, assuming you've already read the Page Layout section, we know we should add headers and footers to the slides. + +Firstly, we add `self.bamboo-title = []`. This means we save the title of the current slide as a member variable `self.bamboo-title`, stored in `self`. This makes it easy to use in the header and later modifications. Similarly, we create `self.bamboo-footer`, saving the `footer: []` parameter from the `register` function for displaying in the bottom-left corner. + +It's worth noting that our header is actually a content function in the form of `let header(self) = { .. }` with the `self` parameter, allowing us to get the latest information from `self`. For example, `self.bamboo-title`. The footer is similar. + +The `components.cell` used inside is actually `#let cell = block.with(width: 100%, height: 100%, above: 0pt, below: 0pt, breakable: false)`, and `show: components.cell` is shorthand for `components.cell(body)`. The `show: pad.with(.4em)` in the footer is similar. + +Another point to note is the `states` module, which contains many counters and state-related content. For example, `states.current-section-title` is used to display the current `section`, and `states.slide-counter.display() + " / " + states.last-slide-number` is used to display the current page number and total number of pages. + +We observe the usage of `utils.call-or-display(self, self.bamboo-footer)` to display `self.bamboo-footer`. This is used to handle situations like `self.bamboo-footer = (self) => {..}`, ensuring a unified approach to displaying content functions and content. + +To ensure proper display of the header and footer and sufficient spacing from the main content, we also set top and bottom margins and left and right padding, such as `self.page-args += (margin: (top: 4em, bottom: 1.5em, x: 0em))` and `self.padding = (x: 2em, y: 0em)`. The left and right margin is `0em` to allow the header to occupy the full page width. The left and right spacing of the main content is achieved through left and right padding of `2em`. + +We also need to customize a `slide` method that accepts `slide(self: none, title: auto, ..args)`. The first `self: none` is a required method parameter for getting the latest `self`. The second `title` is used to update `self.bamboo-title` for displaying in the header. The third `..args` collects the remaining parameters and passes them to `(self.methods.touying-slide)(self: self, ..args)`, which is necessary for the Touying `slide` functionality to work properly. Additionally, we need to register this method in the `register` function with `self.methods.slide = slide`. + +```typst +// bamboo.typ +#import "@preview/touying:0.3.2": * + +#let slide(self: none, title: auto, ..args) = { + if title != auto { + self.bamboo-title = title + } + (self.methods.touying-slide)(self: self, ..args) +} + +#let register( + self: themes.default.register(), + aspect-ratio: "16-9", + footer: [], +) = { + // color theme + self = (self.methods.colors)( + self: self, + primary: rgb("#5E8B65"), + neutral-lightest: rgb("#ffffff"), + neutral-darkest: rgb("#000000"), + ) + // variables for later use + self.bamboo-title = [] + self.bamboo-footer = footer + // set page + let header(self) = { + set align(top) + show: components.cell.with(fill: self.colors.primary, inset: 1em) + set align(horizon) + set text(fill: self.colors.neutral-lightest, size: .7em) + states.current-section-title + linebreak() + set text(size: 1.5em) + utils.call-or-display(self, self.bamboo-title) + } + let footer(self) = { + set align(bottom) + show: pad.with(.4em) + set text(fill: self.colors.neutral-darkest, size: .8em) + utils.call-or-display(self, self.bamboo-footer) + h(1fr) + states.slide-counter.display() + " / " + states.last-slide-number + } + self.page-args += ( + paper: "presentation-" + aspect-ratio, + header: header, + footer: footer, + margin: (top: 4em, bottom: 1.5em, x: 0em), + ) + self.padding = (x: 2em, y: 0em) + // register methods + self.methods.slide = slide + self.methods.alert = (self: none, it) => text(fill: self.colors.primary, it) + self.methods.init = (self: none, body) => { + set text(size: 20pt) + body + } + self +} + + +// main.typ +#import "@preview/touying:0.3.2": * +#import "bamboo.typ" + +#let s = bamboo.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide,) = utils.slides(s) +#show: slides + += First Section + +== First Slide + +#slide[ + A slide with a title and an *important* information. +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/d33bcda7-c032-4b11-b392-5b939d9a0a47) + +## Custom Special Slide + +Building upon the basic slide, we further add some special slide functions such as `title-slide`, `focus-slide`, and a custom `slides` method. + +For the `title-slide` method, first, we call `self = utils.empty-page(self)`. This function clears `self.page-args.header`, `self.page-args.footer`, and sets `margin` and `padding` to `0em`, creating a blank page effect. Then, we use `let info = self.info + args.named()` to get information stored in `self.info` and update it with the passed `args.named()` for later use as `info.title`. The specific page content `body` will vary for each theme, so we won't go into details here. Finally, we call `(self.methods.touying-slide)(self: self, repeat: none, body + +)`, where `repeat: none` indicates that this page does not require animation effects, and passing the `body` parameter displays its content. + +For the `new-section-slide` method, the process is similar. The only thing to note is that in `(self.methods.touying-slide)(self: self, repeat: none, section: section, body)`, we pass an additional `section: section` parameter to declare the creation of a new section. Another point to note is that besides `self.methods.new-section-slide = new-section-slide`, we also register `self.methods.touying-new-section-slide = new-section-slide`, so `new-section-slide` will be automatically called when encountering a first-level title. + +For the `focus-slide` method, most of the content is similar, but it's worth noting that we use `self.page-args += (..)` to update the page's background color. + +Finally, we update the `slides(self: none, title-slide: true, slide-level: 1, ..args)` method. When `title-slide` is `true`, using `#show: slides` will automatically create a `title-slide`. Setting `slide-level: 1` indicates that the first-level and second-level titles correspond to `section` and `title`, respectively. + +``` +// bamboo.typ +#import "@preview/touying:0.3.2": * + +#let slide(self: none, title: auto, ..args) = { + if title != auto { + self.bamboo-title = title + } + (self.methods.touying-slide)(self: self, ..args) +} + +#let title-slide(self: none, ..args) = { + self = utils.empty-page(self) + let info = self.info + args.named() + let body = { + set align(center + horizon) + block( + fill: self.colors.primary, + width: 80%, + inset: (y: 1em), + radius: 1em, + text(size: 2em, fill: self.colors.neutral-lightest, weight: "bold", info.title) + ) + set text(fill: self.colors.neutral-darkest) + if info.author != none { + block(info.author) + } + if info.date != none { + block(if type(info.date) == datetime { info.date.display(self.datetime-format) } else { info.date }) + } + } + (self.methods.touying-slide)(self: self, repeat: none, body) +} + +#let new-section-slide(self: none, section) = { + self = utils.empty-page(self) + let body = { + set align(center + horizon) + set text(size: 2em, fill: self.colors.primary, weight: "bold", style: "italic") + section + } + (self.methods.touying-slide)(self: self, repeat: none, section: section, body) +} + +#let focus-slide(self: none, body) = { + self = utils.empty-page(self) + self.page-args += ( + fill: self.colors.primary, + margin: 2em, + ) + set text(fill: self.colors.neutral-lightest, size: 2em) + (self.methods.touying-slide)(self: self, repeat: none, align(horizon + center, body)) +} + +#let slides(self: none, title-slide: true, slide-level: 1, ..args) = { + if title-slide { + (self.methods.title-slide)(self: self) + } + (self.methods.touying-slides)(self: self, slide-level: slide-level, ..args) +} + +#let register( + self: themes.default.register(), + aspect-ratio: "16-9", + footer: [], +) = { + // color theme + self = (self.methods.colors)( + self: self, + primary: rgb("#5E8B65"), + neutral-lightest: rgb("#ffffff"), + neutral-darkest: rgb("#000000"), + ) + // variables for later use + self.bamboo-title = [] + self.bamboo-footer = footer + // set page + let header(self) = { + set align(top) + show: components.cell.with(fill: self.colors.primary, inset: 1em) + set align(horizon) + set text(fill: self.colors.neutral-lightest, size: .7em) + states.current-section-title + linebreak() + set text(size: 1.5em) + utils.call-or-display(self, self.bamboo-title) + } + let footer(self) = { + set align(bottom) + show: pad.with(.4em) + set text(fill: self.colors.neutral-darkest, size: .8em) + utils.call-or-display(self, self.bamboo-footer) + h(1fr) + states.slide-counter.display() + " / " + states.last-slide-number + } + self.page-args += ( + paper: "presentation-" + aspect-ratio, + header: header, + footer: footer, + margin: (top: 4em, bottom: 1.5em, x: 0em), + ) + self.padding = (x: 2em, y: 0em) + // register methods + self.methods.slide = slide + self.methods.title-slide = title-slide + self.methods.new-section-slide = new-section-slide + self.methods.touying-new-section-slide = new-section-slide + self.methods.focus-slide = focus-slide + self.methods.slides = slides + self.methods.alert = (self: none, it) => text(fill: self.colors.primary, it) + self.methods.init = (self: none, body) => { + set text(size: 20pt) + body + } + self +} + + +// main.typ +#import "@preview/touying:0.3.2": * +#import "bamboo.typ" + +#let s = bamboo.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, focus-slide) = utils.slides(s) +#show: slides + += First Section + +== First Slide + +#slide[ + A slide with a title and an *important* information. +] + +#focus-slide[ + Focus on it! +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/03c5ad02-8ff4-4068-9664-d9cfad79baaf) + + +## Conclusion + +Congratulations! You've created a simple and elegant theme. Perhaps you may find that Touying introduces a wealth of concepts, making it initially challenging to grasp. This is normal, as Touying opts for functionality over simplicity. However, thanks to Touying's comprehensive and unified approach, you can easily extract commonalities between different themes and transfer your knowledge seamlessly. You can also save global variables, modify existing themes, or switch between themes effortlessly, showcasing the benefits of Touying's decoupling and object-oriented programming. \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/changelog.md b/docs/versioned_docs/version-0.3.2+/changelog.md new file mode 100644 index 000000000..be5613796 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/changelog.md @@ -0,0 +1,81 @@ +--- +sidebar_position: 14 +--- + +# Changelog + +## v0.3.2 + +- **fix critical bug:** fix `is-sequence` function, make `grid` and `table` work correctly in touying +- **theme:** add aqua theme, thanks for pride7 +- **theme:** make university theme more configurable +- **refactor:** don't export variable `s` by default anymore, it will be extracted by `register` function (**Breaking Change**) +- **meta:** add `categories` and `template` config to `typst.toml` for Typst 0.11 + + +## v0.3.1 + +- fix some typos +- fix slide-level bug +- fix bug of pdfpc label + + +## v0.3.0 + +### Features + +- better show-slides mode. +- support align and pad. + +### Documentation + +- Add more detailed documentation. + +### Refactor + +- simplify theme. + +### Fix + +- fix many bugs. + +## v0.2.1 + +### Features + +- **Touying-reducer**: support cetz and fletcher animation +- **university theme**: add university theme + +### Fix + +- fix footer progress in metropolis theme +- fix some bugs in simple and dewdrop themes +- fix bug that outline does not display more than 4 sections + + +## v0.2.0 + +- **Object-oriented programming:** Singleton `s`, binding methods `utils.methods(s)` and `(self: obj, ..) => {..}` methods. +- **Page arguments management:** Instead of using `#set page(..)`, you should use `self.page-args` to retrieve or set page parameters, thereby avoiding unnecessary creation of new pages. +- **`#pause` for sequence content:** You can use #pause at the outermost level of a slide, including inline and list. +- **`#pause` for layout functions:** You can use the `composer` parameter to add yourself layout function like `utils.side-by-side`, and simply use multiple pos parameters like `#slide[..][..]`. +- **`#meanwhile` for synchronous display:** Provide a `#meanwhile` for resetting subslides counter. +- **`#pause` and `#meanwhile` for math equation:** Provide a `#touying-equation("x + y pause + z")` for math equation animations. +- **Slides:** Create simple slides using standard headings. +- **Callback-style `uncover`, `only` and `alternatives`:** Based on the concise syntax provided by Polylux, allow precise control of the timing for displaying content. + - You should manually control the number of subslides using the `repeat` parameter. +- **Transparent cover:** Enable transparent cover using oop syntax like `#let s = (s.methods.enable-transparent-cover)(self: s)`. +- **Handout mode:** enable handout mode by `#let s = (s.methods.enable-handout-mode)(self: s)`. +- **Fit-to-width and fit-to-height:** Fit-to-width for title in header and fit-to-height for image. + - `utils.fit-to-width(grow: true, shrink: true, width, body)` + - `utils.fit-to-height(width: none, prescale-width: none, grow: true, shrink: true, height, body)` +- **Slides counter:** `states.slide-counter.display() + " / " + states.last-slide-number` and `states.touying-progress(ratio => ..)`. +- **Appendix:** Freeze the `last-slide-number` to prevent the slide number from increasing further. +- **Sections:** Touying's built-in section support can be used to display the current section title and show progress. + - `section` and `subsection` parameter in `#slide` to register a new section or subsection. + - `states.current-section-title` to get the current section. + - `states.touying-outline` or `s.methods.touying-outline` to display a outline of sections. + - `states.touying-final-sections(sections => ..)` for custom outline display. + - `states.touying-progress-with-sections((current-sections: .., final-sections: .., current-slide-number: .., last-slide-number: ..) => ..)` for powerful progress display. +- **Navigation bar**: Navigation bar like [here](https://github.com/zbowang/BeamerTheme) by `states.touying-progress-with-sections(..)`, in `dewdrop` theme. +- **Pdfpc:** pdfpc support and export `.pdfpc` file without external tool by `typst query` command simply. diff --git a/docs/versioned_docs/version-0.3.2+/code-styles.md b/docs/versioned_docs/version-0.3.2+/code-styles.md new file mode 100644 index 000000000..a2ba82954 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/code-styles.md @@ -0,0 +1,167 @@ +--- +sidebar_position: 4 +--- + +# Code Style + +## Simple Style + +If we only need simplicity, we can directly input content under the heading, just like writing a normal Typst document. The heading here serves to divide the pages, and we can use commands like `#pause` to achieve animation effects. + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register() +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/f5bdbf8f-7bf9-45fd-9923-0fa5d66450b2) + +You can use an empty heading `==` to create a new page. This skill also helps clear the continuation of the previous title. + +PS: We can use the `#slides-end` marker to signify the end of `#show: slides`. + +## Block Style + +Many times, using simple style alone cannot achieve all the functions we need. For more powerful features and clearer structure, we can also use block style in the form of `#slide[...]`. The `#slide` function needs to be unpacked using the syntax `#let (slide,) = utils.slides(s)` to be used correctly after `#show: slides`. + +For example, the previous example can be transformed into: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register() +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides + += Title + +== First Slide + +#slide[ + Hello, Touying! + + #pause + + Hello, Typst! +] +``` + +There are many advantages to doing this: + +1. Many times, we not only need the default `#slide[...]` but also special `slide` functions like `#focus-slide[...]`. +2. Different themes' `#slide[...]` functions may have more parameters than the default, such as the university theme's `#slide[...]` function having a `subtitle` parameter. +3. Only `slide` functions can use the callback-style content block to achieve complex animation effects with `#only` and `#uncover` functions. +4. It has a clearer structure. By identifying `#slide[...]` blocks, we can easily distinguish the specific pagination effects of slides. + +## Convention Over Configuration + +You may have noticed that when using the simple theme, using a level-one heading automatically creates a new section slide. This is because the simple theme registers an `s.methods.touying-new-section-slide` method, so Touying will automatically call this method. + +If we don't want it to automatically create such a section slide, we can delete this method: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register() +#(s.methods.touying-new-section-slide = none) +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/17a89a59-9491-4e1f-95c0-09a22105ab35) + +As you can see, there are only two pages left, and the default section slide is gone. + +Similarly, we can register a new section slide: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register() +#(s.methods.touying-new-section-slide = (self: none, section, ..args) => { + self = utils.empty-page(self) + (s.methods.touying-slide)(self: self, section: section, { + set align(center + horizon) + set text(size: 2em, fill: s.colors.primary, style: "italic", weight: "bold") + section + }, ..args) +}) +#let (init, slides, touying-outline) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/5305efda-0cd4-42eb-9f2e-89abc30b6ca2) + +Similarly, we can modify `s.methods.touying-new-subsection-slide` to do the same for `subsection`. + +In fact, besides `s.methods.touying-new-section-slide`, another special `slide` function is the `s.methods.slide` function, which will be called by default in simple style when `#slide[...]` is not explicitly used. + +Also, since `#slide[...]` is registered in `s.slides = ("slide",)`, the `section`, `subsection`, and `title` parameters will be automatically passed, while others like `#focus-slide[...]` will not automatically receive these three parameters. + +:::tip[Principle] + +In fact, you can also not use `#show: slides` and `utils.slides(s)`, but only use `utils.methods(s)`, for example: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register() +#let (init, touying-outline, slide) = utils.methods(s) +#show: init + +#slide(section: [Title], title: [First Slide])[ + Hello, Touying! + + #pause + + Hello, Typst! +] +``` + +Here, you need to manually pass in `section`, `subsection`, and `title`, but it will have better performance, suitable for cases where faster performance is needed, such as when there are more than dozens or hundreds of pages. + +::: \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/dynamic/_category_.json b/docs/versioned_docs/version-0.3.2+/dynamic/_category_.json new file mode 100644 index 000000000..e6972f365 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/dynamic/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Dynamic Slides", + "position": 7, + "link": { + "type": "generated-index", + "description": "To create animations in PDF, we need to create multiple slightly different pages for the same slide. This allows animation by switching between these pages, and we refer to these pages as subslides." + } +} \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/dynamic/complex.md b/docs/versioned_docs/version-0.3.2+/dynamic/complex.md new file mode 100644 index 000000000..8f99b6888 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/dynamic/complex.md @@ -0,0 +1,78 @@ +--- +sidebar_position: 2 +--- + +# Complex Animations + +Thanks to the syntax provided by [Polylux](https://polylux.dev/book/dynamic/syntax.html), we can also use `only`, `uncover`, and `alternatives` in Touying. + +## Callback-Style Functions + +To overcome the limitations of `styled` and `layout` mentioned earlier, Touying cleverly implements always-effective `only`, `uncover`, and `alternatives` using callback functions. Specifically, you need to introduce these three functions as follows: + +```typst +#slide(repeat: 3, self => [ + #let (uncover, only, alternatives) = utils.methods(self) + + In subslide #self.subslide, + + test #uncover("2-")[uncover] function, + + and test #only("2-")[only] function, + + #pause + + and paused text. +]) +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/e9a6b8c5-daf0-4cf2-8d39-1a768ce1dfea) + +Notice that we no longer pass a content block but instead pass a callback function with a `self` parameter. Later, we extract `only`, `uncover`, and `alternatives` functions from `self` using: + +```typst +#let (uncover, only, alternatives) = utils.methods(self) +``` + +We then call these functions in subsequent steps. + +Here's an interesting fact: the `self.subslide` of type int indicates the current subslide index, and in fact, the `only`, `uncover`, and `alternatives` functions rely on `self.subslide` to determine the current subslide index. + +:::warning[Warning] + +We manually specify the `repeat: 3` parameter, indicating the display of 3 subslides. We need to do this manually because Touying cannot infer how many subslides `only`, `uncover`, and `alternatives` should display. + +::: + +## only + +The `only` function means it "appears" only on selected subslides. If it doesn't appear, it completely disappears and doesn't occupy any space. In other words, `#only(index, body)` is either `body` or `none`. + +The index can be an int type or a str type like `"2-"` or `"2-3"`. For more usage, refer to [Polylux](https://polylux.dev/book/dynamic/complex.html). + +## uncover + +The `uncover` function means it "displays" only on selected subslides; otherwise, it will be covered by the `cover` function but still occupies the original space. In other words, `#uncover(index, body)` is either `body` or `cover(body)`. + +The index can be an int type or a str type like `"2-"` or `"2-3"`. For more usage, refer to [Polylux](https://polylux.dev/book/dynamic/complex.html). + +You may also have noticed that `#pause` actually uses the `cover` function, providing a more convenient syntax. In reality, their effects are almost identical. + +## alternatives + +The `alternatives` function displays a series of different content in different subslides. For example: + +```typst +#slide(repeat: 3, self => [ + #let (uncover, only, alternatives) = utils.methods(self) + + #alternatives[Ann][Bob][Christopher] + likes + #alternatives[chocolate][strawberry][vanilla] + ice cream. +]) +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/392707ea-0bcd-426b-b232-5bc63b9a13a3) + +As you can see, `alternatives` can automatically expand to the most suitable width and height, a capability that `only` and `uncover` lack. In fact, `alternatives` has other parameters, such as `start: 2`, `repeat-last: true`, and `position: center + horizon`. For more usage, refer to [Polylux](https://polylux.dev/book/dynamic/alternatives.html). \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/dynamic/cover.md b/docs/versioned_docs/version-0.3.2+/dynamic/cover.md new file mode 100644 index 000000000..e9178b11e --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/dynamic/cover.md @@ -0,0 +1,67 @@ +--- +sidebar_position: 4 +--- + +# Cover Function + +As you already know, both `uncover` and `#pause` use the `cover` function to conceal content that is not visible. So, what exactly is the `cover` function here? + +## Default Cover Function: `hide` + +The `cover` function is a method stored in `s.methods.cover`, which is later used by `uncover` and `#pause`. + +The default `cover` function is the [hide](https://typst.app/docs/reference/layout/hide/) function. This function makes the internal content invisible without affecting the layout. + +## Updating the Cover Function + +In some cases, you might want to use your own `cover` function. In that case, you can set your own `cover` function using: + +```typst +let s = (s.methods.update-cover)(self: s, is-method: true, cover-fn) +``` + +Here, if you set `is-method: false`, Touying will wrap `cover-fn` into a method for you. + +## Semi-Transparent Cover Function + +Touying supports a semi-transparent cover function, which can be enabled by adding: + +```typst +#let s = (s.methods.enable-transparent-cover)(self: s) +``` + +You can adjust the transparency through the `alpha: ..` parameter. + +:::warning[Warning] + +Note that the `transparent-cover` here does not preserve text layout like `hide` does because it adds an extra layer of `box`, which may disrupt the original structure of the page. + +::: + +:::tip[Internals] + +The `enable-transparent-cover` method is defined as: + +```typst +#let s.methods.enable-transparent-cover = ( + self: none, + constructor: rgb, + alpha: 85%, +) => { + self.methods.cover = (self: none, body) => { + utils.cover-with-rect( + fill: utils.update-alpha( + constructor: constructor, + self.page-args.fill, + alpha, + ), + body + ) + } + self +} +``` + +It creates a semi-transparent rectangular mask with the same color as the background to simulate the effect of transparent content. Here, `constructor: rgb` and `alpha: 85%` indicate the background color's construction function and transparency level, respectively. + +::: \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/dynamic/equation.md b/docs/versioned_docs/version-0.3.2+/dynamic/equation.md new file mode 100644 index 000000000..9b9c80fa4 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/dynamic/equation.md @@ -0,0 +1,67 @@ +--- +sidebar_position: 3 +--- + +# Math Equation Animations + +Touying also provides a unique and highly useful feature—math equation animations, allowing you to conveniently use `pause` and `meanwhile` within math equations. + +## Simple Animation + +Let's start with an example: + +```typst +#slide[ + Touying equation with pause: + + #touying-equation(` + f(x) &= pause x^2 + 2x + 1 \ + &= pause (x + 1)^2 \ + `) + + #meanwhile + + Touying equation is very simple. +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/d176e61f-c0da-4c2a-a1bf-52621be5adb2) + +We use the `touying-equation` function to incorporate `pause` and `meanwhile` within the text of math equations (in fact, you can also use `#pause` or `#pause;`). + +As you would expect, the math equation is displayed step by step, making it suitable for presenters to demonstrate their math reasoning. + +:::warning[Warning] + +While the `touying-equation` function is convenient, you should always be aware that it doesn't perform complex syntax analysis. It simply splits the string using regular expressions. Therefore, you should not use `pause` or `meanwhile` within functions like `display(..)`! + +::: + +## Complex Animation + +In fact, we can also use `only`, `uncover`, and `alternatives` within `touying-equation` with a little trick: + +```typst +#slide(repeat: 3, self => [ + #let (uncover, only, alternatives) = utils.methods(self) + + #touying-equation(scope: (uncover: uncover), ` + f(x) &= pause x^2 + 2x + uncover("3-", 1) \ + &= pause (x + 1)^2 \ + `) +]) +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/f2df14a2-6424-4c53-81f7-1595aa330660) + +We can pass the functions we need into the `touying-equation` through the `scope` parameter, such as `uncover` in this example. + +## Parameters + +The function definition of `touying-equation` is: + +```typst +#let touying-equation(block: true, numbering: none, supplement: auto, scope: (:), body) = { .. } +``` + +Therefore, you can pass parameters like `block`, `numbering`, and `supplement` to `touying-equation` just like using normal math equations. \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/dynamic/handout.md b/docs/versioned_docs/version-0.3.2+/dynamic/handout.md new file mode 100644 index 000000000..f80713d2f --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/dynamic/handout.md @@ -0,0 +1,15 @@ +--- +sidebar_position: 6 +--- + +# Handout Mode + +While watching slides and attending lectures, the audience often wishes to have handouts for reviewing challenging concepts. Therefore, it's beneficial for the author to provide handouts for the audience, preferably before the lecture for better preparation. + +The handout mode differs from the regular mode as it doesn't require intricate animation effects. It retains only the last subslide of each slide. + +Enabling handout mode is simple: + +```typst +#let s = (s.methods.enable-handout-mode)(self: s) +``` diff --git a/docs/versioned_docs/version-0.3.2+/dynamic/other.md b/docs/versioned_docs/version-0.3.2+/dynamic/other.md new file mode 100644 index 000000000..026d6466c --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/dynamic/other.md @@ -0,0 +1,100 @@ +--- +sidebar_position: 5 +--- + +# Other Animations + +Touying also provides `touying-reducer`, which adds `pause` and `meanwhile` animations to cetz and fletcher. + +## Simple Animations + +Here's an example: + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/cetz:0.2.1" +#import "@preview/fletcher:0.4.2" as fletcher: node, edge + +#let cetz-canvas = touying-reducer.with(reduce: cetz.canvas, cover: cetz.draw.hide.with(bounds: true)) +#let fletcher-diagram = touying-reducer.with(reduce: (arr, ..args) => fletcher.diagram(..args, ..arr)) + +#let s = themes.metropolis.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides.with(title-slide: false, outline-slide: false) + +// cetz animation +#slide[ + Cetz in Touying: + + #cetz-canvas({ + import cetz.draw: * + + rect((0,0), (5,5)) + + (pause,) + + rect((0,0), (1,1)) + rect((1,1), (2,2)) + rect((2,2), (3,3)) + + (pause,) + + line((0,0), (2.5, 2.5), name: "line") + }) +] + +// fletcher animation +#slide[ + Fletcher in Touying: + + #fletcher-diagram( + node-stroke: .1em, + node-fill: gradient.radial(blue.lighten(80%), blue, center: (30%, 20%), radius: 80%), + spacing: 4em, + edge((-1,0), "r", "-|>", `open(path)`, label-pos: 0, label-side: center), + node((0,0), `reading`, radius: 2em), + edge((0,0), (0,0), `read()`, "--|>", bend: 130deg), + pause, + edge(`read()`, "-|>"), + node((1,0), `eof`, radius: 2em), + pause, + edge(`close()`, "-|>"), + node((2,0), `closed`, radius: 2em, extrude: (-2.5, 0)), + edge((0,0), (2,0), `close()`, "-|>", bend: -40deg), + ) +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/9ba71f54-2a5d-4144-996c-4a42833cc5cc) + + +## only and uncover + +In fact, we can also use `only` and `uncover` within cetz, just requiring a bit of skill: + +```typst +#slide(repeat: 3, self => [ + #let (uncover, only) = utils.methods(self) + + Cetz in Touying in subslide #self.subslide: + + #cetz.canvas({ + import cetz.draw: * + let self = (self.methods.update-cover)(self: self, hide) + let (uncover,) = utils.methods(self) + + rect((0,0), (5,5)) + + uncover("2-3", { + rect((0,0), (1,1)) + rect((1,1), (2,2)) + rect((2,2), (3,3)) + }) + + only(3, line((0,0), (2.5, 2.5), name: "line")) + }) +]) +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/dynamic/simple.md b/docs/versioned_docs/version-0.3.2+/dynamic/simple.md new file mode 100644 index 000000000..a373bbc2c --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/dynamic/simple.md @@ -0,0 +1,82 @@ +--- +sidebar_position: 1 +--- + +# Simple Animations + +Touying provides two markers for simple animation effects: `#pause` and `#meanwhile`. + +## pause + +The purpose of `#pause` is straightforward – it separates the subsequent content into the next subslide. You can use multiple `#pause` to create multiple subslides. Here's a simple example: + +```typst +#slide[ + First #pause Second + + #pause + + Third +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/a3bed1d3-e660-456d-8a54-a914436f43bf) + +This example will create three subslides, gradually revealing the content. + +As you can see, `#pause` can be used inline or on a separate line. + +## meanwhile + +In some cases, you may need to display additional content simultaneously with `#pause`. In such cases, you can use `#meanwhile`. + +```typst +#slide[ + First + + #pause + + Second + + #meanwhile + + Third + + #pause + + Fourth +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/24ca19a3-b27c-4d31-ab75-09c37911e6ac) + +This example will create only two subslides, with "First" and "Third" displayed simultaneously, and "Second" and "Fourth" displayed simultaneously. + +## Handling set-show rules + +If you use set-show rules inside `slide[..]`, you might be surprised to find that subsequent `#pause` and `#meanwhile` do not work. This is because Touying cannot detect the content inside `styled(..)` (content after set-show rules is encompassed by `styled`). + +To address this issue, Touying provides a `setting` parameter for the `#slide()` function. You can place your set-show rules in the `setting` parameter. For example, changing the font color: + +```typst +#slide(setting: body => { + set text(fill: blue) + body +})[ + First + + #pause + + Second +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/8e31fc8a-5ab1-4181-a46a-fa96cf790dff) + +Similarly, Touying currently does not support `#pause` and `#meanwhile` inside layout functions like `grid`. This is due to the same limitation, but you can use the `composer` parameter of `#slide()` to meet most requirements. + +:::tip[Internals] + +Touying doesn't rely on `counter` and `locate` to implement `#pause`. Instead, it has a parser written in Typst script. It parses the input content block as a sequence and then transforms and reorganizes this sequence into the series of subslides we need. + +::: \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/external/_category_.json b/docs/versioned_docs/version-0.3.2+/external/_category_.json new file mode 100644 index 000000000..47d3f800a --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/external/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "External Tools", + "position": 13, + "link": { + "type": "generated-index", + "description": "Integrate external tools with Touying." + } +} \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/external/pdfpc.md b/docs/versioned_docs/version-0.3.2+/external/pdfpc.md new file mode 100644 index 000000000..58c06f85d --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/external/pdfpc.md @@ -0,0 +1,58 @@ +--- +sidebar_position: 1 +--- + +# Pdfpc + +[pdfpc](https://pdfpc.github.io/) is a "Presenter Console with multi-monitor support for PDF files." This means you can use it to display slides in the form of PDF pages and it comes with some known excellent features, much like PowerPoint. + +pdfpc has a JSON-formatted `.pdfpc` file that can provide additional information for PDF slides. While you can manually write this file, you can also manage it through Touying. + + +## Adding Metadata + +Touying remains consistent with [Polylux](https://polylux.dev/book/external/pdfpc.html) to avoid conflicts between APIs. + +For example, you can add notes using `#pdfpc.speaker-note("This is a note that only the speaker will see.")`. + + +## Pdfpc Configuration + +To add pdfpc configurations, you can use + +```typst +#let s = (s.methods.append-preamble)(self: s, pdfpc.config( + duration-minutes: 30, + start-time: datetime(hour: 14, minute: 10, second: 0), + end-time: datetime(hour: 14, minute: 40, second: 0), + last-minutes: 5, + note-font-size: 12, + disable-markdown: false, + default-transition: ( + type: "push", + duration-seconds: 2, + angle: ltr, + alignment: "vertical", + direction: "inward", + ), +)) +``` + +Add the corresponding configurations. Refer to [Polylux](https://polylux.dev/book/external/pdfpc.html) for specific configuration details. + + +## Exporting .pdfpc File + +Assuming your document is `./example.typ`, you can export the `.pdfpc` file directly using: + +```sh +typst query --root . ./example.typ --field value --one "" > ./example.pdfpc +``` + +With the compatibility of Touying and Polylux, you can make Polylux also support direct export by adding the following code: + +```typst +#import "@preview/touying:0.3.2" + +#locate(loc => touying.pdfpc.pdfpc-file(loc)) +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/external/typst-preview.md b/docs/versioned_docs/version-0.3.2+/external/typst-preview.md new file mode 100644 index 000000000..6738038ce --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/external/typst-preview.md @@ -0,0 +1,15 @@ +--- +sidebar_position: 2 +--- + +# Typst Preview + +The Typst Preview extension for VS Code provides an excellent slide mode, allowing us to preview and present slides. + +Press `Ctrl/Cmd + Shift + P` and type `Typst Preview: Preview current file in slide mode` to open the preview in slide mode. + +Press `Ctrl/Cmd + Shift + P` and type `Typst Preview: Preview current file in browser and slide mode` to open the slide mode in the browser. + +Now, you can press keys like `F11` to enter fullscreen mode in the browser, making it suitable for slide presentations. + +Since Typst Preview is based on SVG, it can play GIF animations, which is very helpful for dynamic slides. \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/global-settings.md b/docs/versioned_docs/version-0.3.2+/global-settings.md new file mode 100644 index 000000000..8caf9dc1a --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/global-settings.md @@ -0,0 +1,169 @@ +--- +sidebar_position: 6 +--- + +# Global Settings + +## Global Styles + +For Touying, global styles refer to set rules or show rules that need to be applied everywhere, such as `#set text(size: 20pt)`. + +Themes in Touying encapsulate some of their own global styles, which are placed in `#show: init`. For example, the university theme encapsulates the following: + +```typst +self.methods.init = (self: none, body) => { + set text(size: 25pt) + show footnote.entry: set text(size: .6em) + body +} +``` + +If you are not a theme creator but want to add your own global styles to your slides, you can simply place them after `#show: init` and before `#show: slides`. For example, the metropolis theme recommends adding the following global styles: + +```typst +#let s = themes.metropolis.register(aspect-ratio: "16-9") +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +// global styles +#set text(font: "Fira Sans", weight: "light", size: 20pt) +#show math.equation: set text(font: "Fira Math") +#set strong(delta: 100) +#set par(justify: true) +#show strong: alert + +#let (slide, title-slide, new-section-slide, focus-slide) = utils.slides(s) +#show: slides +``` + +However, note that you should not use `#set page(..)`. Instead, modify `s.page-args` and `s.padding`, for example: + +```typst +#(s.page-args += ( + margin: (x: 0em, y: 2em), + header: align(top)[Header], + footer: align(bottom)[Footer], + header-ascent: 0em, + footer-descent: 0em, +)) +#(s.padding += (x: 4em, y: 0em)) +``` + +## Global Information + +Like Beamer, Touying, through an OOP-style unified API design, can help you better maintain global information, allowing you to easily switch between different themes. Global information is a typical example of this. + +You can set the title, subtitle, author, date, and institution information for slides using: + +```typst +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +``` + +In subsequent slides, you can access them through `s.info` or `self.info`. + +This information is generally used in the title-slide, header, and footer of the theme, for example: + +```typst +#let s = themes.metropolis.register(aspect-ratio: "16-9", footer: self => self.info.institution) +``` + +The `date` can accept `datetime` format or `content` format, and the display format for the `datetime` format can be changed using: + +```typst +#let s = (s.methods.datetime-format)(self: s, "[year]-[month]-[day]") +``` + +:::tip[Principle] + +Here, we will introduce a bit of OOP concept in Touying. + +You should know that Typst is a typesetting language that supports incremental rendering, which means Typst caches the results of previous function calls. This requires that Typst consists of pure functions, meaning functions that do not change external variables. Thus, it is challenging to modify a global variable in the true sense, even with the use of `state` or `counter`. This would require the use of `locate` with callback functions to obtain the values inside, and this approach would have a significant impact on performance. + +Touying does not use `state` or `counter` and does not violate the principle of pure functions in Typst. Instead, it uses a clever approach in an object-oriented style, maintaining a global singleton `s`. In Touying, an object refers to a Typst dictionary with its own member variables and methods. We agree that methods all have a named parameter `self` for passing the object itself, and methods are placed in the `.methods` domain. With this concept, it becomes easier to write methods to update `info`: + +```typst +#let s = ( + info: (:), + methods: ( + // update info + info: (self: none, ..args) => { + self.info += args.named() + self + }, + ) +) + +#let s = (s.methods.info)(self: s, title: [title]) + +Title is #s.info.title +``` + +Now you can understand the purpose of the `utils.methods()` function: to bind `self` to all methods of `s` and return it, simplifying the subsequent usage through unpacking syntax. + +```typst +#let (init, slides, alert) = utils.methods(s) +``` +::: + +## State Initialization + +In general, the two ways mentioned above are sufficient for adding global settings. However, there are still situations where we need to initialize counters or states. If you place this code before `#show: slides`, a blank page will be created, which is something we don't want to see. In such cases, you can use the `s.methods.append-preamble` method. For example, when using the codly package: + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/codly:0.2.0": * + +#let s = themes.simple.register(aspect-ratio: "16-9") +#let s = (s.methods.append-preamble)(self: s)[ + #codly(languages: ( + rust: (name: "Rust", icon: "\u{fa53}", color: rgb("#CE412B")), + )) +] +#let (init, slides) = utils.methods(s) +#show heading.where(level: 2): set block(below: 1em) +#show: init +#show: codly-init.with() + +#let (slide,) = utils.slides(s) +#show: slides + +#slide[ + == First slide + + #raw(lang: "rust", block: true, +`pub fn main() { + println!("Hello, world!"); +}`.text) +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/0be2fbaf-cc03-4776-932f-259503d5e23a) + +Or when configuring Pdfpc: + +```typst +// Pdfpc configuration +// typst query --root . ./example.typ --field value --one "" > ./example.pdfpc +#let s = (s.methods.append-preamble)(self: s, pdfpc.config( + duration-minutes: 30, + start-time: datetime(hour: 14, minute: 10, second: 0), + end-time: datetime(hour: 14, minute: 40, second: 0), + last-minutes: 5, + note-font-size: 12, + disable-markdown: false, + default-transition: ( + type: "push", + duration-seconds: 2, + angle: ltr, + alignment: "vertical", + direction: "inward", + ), +)) +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/integration/_category_.json b/docs/versioned_docs/version-0.3.2+/integration/_category_.json new file mode 100644 index 000000000..9924b2933 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/integration/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Package Integration", + "position": 8, + "link": { + "type": "generated-index", + "description": "Discover how to integrate third-party packages with Touying." + } +} diff --git a/docs/versioned_docs/version-0.3.2+/integration/cetz.md b/docs/versioned_docs/version-0.3.2+/integration/cetz.md new file mode 100644 index 000000000..2ceecbc57 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/integration/cetz.md @@ -0,0 +1,100 @@ +--- +sidebar_position: 3 +--- + +# CeTZ + +Touying provides the `touying-reducer`, which adds `pause` and `meanwhile` animations to CeTZ and Fletcher. + +## Simple Animation + +An example: + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/cetz:0.2.1" +#import "@preview/fletcher:0.4.2" as fletcher: node, edge + +#let cetz-canvas = touying-reducer.with(reduce: cetz.canvas, cover: cetz.draw.hide.with(bounds: true)) +#let fletcher-diagram = touying-reducer.with(reduce: (arr, ..args) => fletcher.diagram(..args, ..arr)) + +#let s = themes.metropolis.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides.with(title-slide: false, outline-slide: false) + +// cetz animation +#slide[ + Cetz in Touying: + + #cetz-canvas({ + import cetz.draw: * + + rect((0,0), (5,5)) + + (pause,) + + rect((0,0), (1,1)) + rect((1,1), (2,2)) + rect((2,2), (3,3)) + + (pause,) + + line((0,0), (2.5, 2.5), name: "line") + }) +] + +// fletcher animation +#slide[ + Fletcher in Touying: + + #fletcher-diagram( + node-stroke: .1em, + node-fill: gradient.radial(blue.lighten(80%), blue, center: (30%, 20%), radius: 80%), + spacing: 4em, + edge((-1,0), "r", "-|>", `open(path)`, label-pos: 0, label-side: center), + node((0,0), `reading`, radius: 2em), + edge((0,0), (0,0), `read()`, "--|>", bend: 130deg), + pause, + edge(`read()`, "-|>"), + node((1,0), `eof`, radius: 2em), + pause, + edge(`close()`, "-|>"), + node((2,0), `closed`, radius: 2em, extrude: (-2.5, 0)), + edge((0,0), (2,0), `close()`, "-|>", bend: -40deg), + ) +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/9ba71f54-2a5d-4144-996c-4a42833cc5cc) + + +## only and uncover + +In fact, we can also use `only` and `uncover` within CeTZ, but it requires a bit of technique: + +```typst +#slide(repeat: 3, self => [ + #let (uncover, only) = utils.methods(self) + + Cetz in Touying in subslide #self.subslide: + + #cetz.canvas({ + import cetz.draw: * + let self = (self.methods.update-cover)(self: self, hide) + let (uncover,) = utils.methods(self) + + rect((0,0), (5,5)) + + uncover("2-3", { + rect((0,0), (1,1)) + rect((1,1), (2,2)) + rect((2,2), (3,3)) + }) + + only(3, line((0,0), (2.5, 2.5), name: "line")) + }) +]) +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/integration/codly.md b/docs/versioned_docs/version-0.3.2+/integration/codly.md new file mode 100644 index 000000000..636011d15 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/integration/codly.md @@ -0,0 +1,37 @@ +--- +sidebar_position: 5 +--- + +# Codly + +When using Codly, we should initialize it using the `s.methods.append-preamble` method. + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/codly:0.2.0": * + +#let s = themes.simple.register(aspect-ratio: "16-9") +#let s = (s.methods.append-preamble)(self: s)[ + #codly(languages: ( + rust: (name: "Rust", icon: "\u{fa53}", color: rgb("#CE412B")), + )) +] +#let (init, slides) = utils.methods(s) +#show heading.where(level: 2): set block(below: 1em) +#show: init +#show: codly-init.with() + +#let (slide,) = utils.slides(s) +#show: slides + +#slide[ + == First slide + + #raw(lang: "rust", block: true, +`pub fn main() { + println!("Hello, world!"); +}`.text) +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/0be2fbaf-cc03-4776-932f-259503d5e23a) diff --git a/docs/versioned_docs/version-0.3.2+/integration/fletcher.md b/docs/versioned_docs/version-0.3.2+/integration/fletcher.md new file mode 100644 index 000000000..5766ac984 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/integration/fletcher.md @@ -0,0 +1,69 @@ +--- +sidebar_position: 4 +--- + +# Fletcher + +Touying provides the `touying-reducer`, which adds `pause` and `meanwhile` animations to Fletcher. + +An example: + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/cetz:0.2.1" +#import "@preview/fletcher:0.4.2" as fletcher: node, edge + +#let cetz-canvas = touying-reducer.with(reduce: cetz.canvas, cover: cetz.draw.hide.with(bounds: true)) +#let fletcher-diagram = touying-reducer.with(reduce: (arr, ..args) => fletcher.diagram(..args, ..arr)) + +#let s = themes.metropolis.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides.with(title-slide: false, outline-slide: false) + +// cetz animation +#slide[ + Cetz in Touying: + + #cetz-canvas({ + import cetz.draw: * + + rect((0,0), (5,5)) + + (pause,) + + rect((0,0), (1,1)) + rect((1,1), (2,2)) + rect((2,2), (3,3)) + + (pause,) + + line((0,0), (2.5, 2.5), name: "line") + }) +] + +// fletcher animation +#slide[ + Fletcher in Touying: + + #fletcher-diagram( + node-stroke: .1em, + node-fill: gradient.radial(blue.lighten(80%), blue, center: (30%, 20%), radius: 80%), + spacing: 4em, + edge((-1,0), "r", "-|>", `open(path)`, label-pos: 0, label-side: center), + node((0,0), `reading`, radius: 2em), + edge((0,0), (0,0), `read()`, "--|>", bend: 130deg), + pause, + edge(`read()`, "-|>"), + node((1,0), `eof`, radius: 2em), + pause, + edge(`close()`, "-|>"), + node((2,0), `closed`, radius: 2em, extrude: (-2.5, 0)), + edge((0,0), (2,0), `close()`, "-|>", bend: -40deg), + ) +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/9ba71f54-2a5d-4144-996c-4a42833cc5cc) \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/integration/mitex.md b/docs/versioned_docs/version-0.3.2+/integration/mitex.md new file mode 100644 index 000000000..625ab5cd1 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/integration/mitex.md @@ -0,0 +1,26 @@ +--- +sidebar_position: 2 +--- + +# MiTeX + +During the process of creating slides, we often already have a LaTeX math equation that we simply want to paste into the slides without transcribing it into a Typst math equation. In such cases, we can use [MiTeX](https://github.com/mitex-rs/mitex). + +Example: + +```typst +#import "@preview/mitex:0.2.1": * + +Write inline equations like #mi("x") or #mi[y]. + +Also block equations (this case is from #text(blue.lighten(20%), link("https://katex.org/")[katex.org])): + +#mitex(` + \newcommand{\f}[2]{#1f(#2)} + \f\relax{x} = \int_{-\infty}^\infty + \f\hat\xi\,e^{2 \pi i \xi x} + \,d\xi +`) +``` + +![image](https://github.com/mitex-rs/mitex/assets/34951714/c425b2ae-b50b-46a8-a451-4d9e8e70626b) diff --git a/docs/versioned_docs/version-0.3.2+/integration/pinit.md b/docs/versioned_docs/version-0.3.2+/integration/pinit.md new file mode 100644 index 000000000..4281c6956 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/integration/pinit.md @@ -0,0 +1,122 @@ +--- +sidebar_position: 1 +--- + +# Pinit + +[Pinit](https://github.com/OrangeX4/typst-pinit/) package provides the ability to perform absolute positioning based on the page and relative positioning based on "pins," making it convenient to implement arrow pointing and explanatory effects for slides. + +## Simple Example + +```typst +#import "@preview/pinit:0.1.3": * + +#set text(size: 24pt) + +A simple #pin(1)highlighted text#pin(2). + +#pinit-highlight(1, 2) + +#pinit-point-from(2)[It is simple.] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/b17f9b80-5a8b-4943-a222-bcb0eb38611d) + +Another [example](https://github.com/OrangeX4/typst-pinit/blob/main/examples/equation-desc.typ): + +![image](https://github.com/touying-typ/touying/assets/34951714/9b4a6b50-fcfd-497d-9649-ae1f7762ee3f) + + +## Complex Example + +![image](https://github.com/touying-typ/touying/assets/34951714/7fb0095a-fd86-49ec-af95-15bc81a341c2) + +An example of shared usage with Touying: + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/pinit:0.1.3": * + +#(s.page-args.paper = "presentation-4-3") +#let (init, slides) = utils.methods(s) +#show: init + +#set text(size: 20pt, font: "Calibri", ligatures: false) +#show heading: set text(weight: "regular") +#show heading: set block(above: 1.4em, below: 1em) +#show heading.where(level: 1): set text(size: 1.5em) + +// Useful functions +#let crimson = rgb("#c00000") +#let greybox(..args, body) = rect(fill: luma(95%), stroke: 0.5pt, inset: 0pt, outset: 10pt, ..args, body) +#let redbold(body) = { + set text(fill: crimson, weight: "bold") + body +} +#let blueit(body) = { + set text(fill: blue) + body +} + +#let (slide,) = utils.slides(s) +#show: slides + +// Main body +#slide(self => [ + #let (uncover, only) = utils.methods(self) + + = Asymptotic Notation: $O$ + + Use #pin("h1")asymptotic notations#pin("h2") to describe asymptotic efficiency of algorithms. + (Ignore constant coefficients and lower-order terms.) + + #pause + + #greybox[ + Given a function $g(n)$, we denote by $O(g(n))$ the following *set of functions*: + #redbold(${f(n): "exists" c > 0 "and" n_0 > 0, "such that" f(n) <= c dot g(n) "for all" n >= n_0}$) + ] + + #pinit-highlight("h1", "h2") + + #pause + + $f(n) = O(g(n))$: #pin(1)$f(n)$ is *asymptotically smaller* than $g(n)$.#pin(2) + + // #absolute-place(dx: 550pt, dy: 320pt, image(width: 25%, "asymptotic.png")) + + #pause + + $f(n) redbold(in) O(g(n))$: $f(n)$ is *asymptotically* #redbold[at most] $g(n)$. + + #only("4-", pinit-line(stroke: 3pt + crimson, start-dy: -0.25em, end-dy: -0.25em, 1, 2)) + + #pause + + #block[Insertion Sort as an #pin("r1")example#pin("r2"):] + + - Best Case: $T(n) approx c n + c' n - c''$ #pin(3) + - Worst case: $T(n) approx c n + (c' \/ 2) n^2 - c''$ #pin(4) + + #pinit-rect("r1", "r2") + + #pause + + #pinit-place(3, dx: 15pt, dy: -15pt)[#redbold[$T(n) = O(n)$]] + #pinit-place(4, dx: 15pt, dy: -15pt)[#redbold[$T(n) = O(n)$]] + + #pause + + #blueit[Q: Is $n^(3) = O(n^2)$#pin("que")? How to prove your answer#pin("ans")?] + + #pause + + #only("8-", pinit-point-to("que", fill: crimson, redbold[No.])) + #only("8-", pinit-point-from("ans", body-dx: -150pt)[ + Show that the equation $(3/2)^n >= c$ \ + has infinitely many solutions for $n$. + ]) +]) +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/f36a026f-491c-4290-90d5-0aa3c2086567) diff --git a/docs/versioned_docs/version-0.3.2+/integration/polylux.md b/docs/versioned_docs/version-0.3.2+/integration/polylux.md new file mode 100644 index 000000000..c439fd82c --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/integration/polylux.md @@ -0,0 +1,21 @@ +--- +sidebar_position: 6 +--- + +# Polylux + +With the compatibility between Touying and Polylux, you can make Polylux support direct export as well. Just add the following code to your Polylux source code: + +```typst +#import "@preview/touying:0.3.2" + +#locate(loc => touying.pdfpc.pdfpc-file(loc)) +``` + +Assuming your document is `./example.typ`, you can then export the `.pdfpc` file directly using the following command: + +```sh +typst query --root . ./example.typ --field value --one "" > ./example.pdfpc +``` + +This eliminates the need for an additional `polylux2pdfpc` program. \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/intro.md b/docs/versioned_docs/version-0.3.2+/intro.md new file mode 100644 index 000000000..71677848e --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/intro.md @@ -0,0 +1,36 @@ +--- +sidebar_position: 1 +--- + +# Introduction to Touying + +[Touying](https://github.com/touying-typ/touying) is a slide/presentation package developed for Typst. Touying is similar to LaTeX Beamer but benefits from Typst, providing faster rendering speed and a more concise syntax. After, we use "slides" to refer to slideshows, "slide" for a single slide, and "subslide" for a sub-slide. + +## Why Use Touying + +- Unlike PowerPoint, Touying is not a "what you see is what you get" tool. You can write your slides in a "content and style separation" manner, especially with Typst, which offers a concise yet powerful syntax, better supporting content like code blocks, mathematical formulas, and theorems. Another advantage is that, with templates, writing slides with Touying is much faster than PowerPoint. Therefore, Touying is more suitable for users with a demand for "research writing." +- Compared to Markdown Slides, Touying, relying on Typst, has more powerful typesetting control, such as headers, footers, layout, and convenient custom functions. These are capabilities that Markdown struggles to provide, or does not do well. Additionally, Touying offers `#pause` and `#meanwhile` markers, providing more convenient dynamic slide capabilities. +- Compared to Beamer, Touying has faster compilation speed, a more concise syntax, and simpler theme customization capabilities. Touying's compilation speed can be maintained in milliseconds or tens of milliseconds, compared to Beamer's compilation time of seconds or tens of seconds. Touying's syntax is more concise than Beamer, making it easier to change templates and create your own templates. In terms of features, Touying supports most of Beamer's capabilities and provides some convenient features that Beamer lacks. +- Compared to Polylux, Touying provides an object-oriented programming (OOP) style syntax, allowing the simulation of "global variables" through a global singleton. This makes it easy to write themes. Touying does not rely on `counter` and `locate` to implement `#pause`, resulting in better performance. Touying is a community-driven project (we welcome more people to join), and it does not overly emphasize maintaining API consistency. Instead, it chooses to maintain documentation for multiple versions, providing more novel yet powerful features. + +## About the Name + +"Touying" is derived from the Chinese word "投影" (tóuyǐng), which means "projection" In English, it also conveys the meaning of a "project". In comparison, the term "beamer" in LaTeX means a projector in German. + +## About the Documentation + +This documentation is powered by [Docusaurus](https://docusaurus.io/). We will maintain English and Chinese versions of the documentation for Touying, and for each major version, we will maintain a documentation copy. This allows you to easily refer to old versions of the Touying documentation and migrate to new versions. + +Docusaurus creates a new version: + +```sh +npm run docusaurus docs:version 0.y.x +``` + +## Contribution + +Touying is free, open-source, and community-driven. If you're interested, you can visit [GitHub](https://github.com/touying-typ/touying) anytime and raise issues or submit pull requests. We also welcome you to join the [touying-typ](https://github.com/touying-typ) organization. + +## License + +Touying is released under the [MIT license](https://github.com/touying-typ/touying/blob/main/LICENSE). \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/layout.md b/docs/versioned_docs/version-0.3.2+/layout.md new file mode 100644 index 000000000..9da184a92 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/layout.md @@ -0,0 +1,181 @@ +--- +sidebar_position: 5 +--- + +# Page Layout + +## Basic Concepts + +To create aesthetically pleasing slides using Typst, it is essential to understand Typst's page model correctly. If you don't care about customizing the page style, you can choose to skip this section. However, it is still recommended to go through this part. + +Here, we illustrate Typst's default page model with a specific example. + +```typst +#let container = rect.with(height: 100%, width: 100%, inset: 0pt) +#let innerbox = rect.with(stroke: (dash: "dashed")) + +#set text(size: 30pt) +#set page( + paper: "presentation-16-9", + header: container[#innerbox[Header]], + header-ascent: 30%, + footer: container[#innerbox[Footer]], + footer-descent: 30%, +) +#let padding = (x: 2em, y: 2em) + +#place(top + right)[Margin→] +#container[ + #place[Padding] + #pad(..padding)[ + #container[ + #innerbox[Content] + ] + ] +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/6cbb1092-c733-41b6-a15d-822ce970ef13) + +We need to distinguish the following concepts: + +1. **Model:** Typst has a model similar to the CSS Box Model, divided into Margin, Padding, and Content. However, padding is not a property of `set page(..)` but is obtained manually by adding `#pad(..)`. +2. **Margin:** Margins, including top, bottom, left, and right, are the core of Typst's page model. Other properties are influenced by margins, especially Header and Footer, which are actually inside the Margin. +3. **Padding:** Used to add additional space between Margin and Content. +4. **Header:** The Header is the content at the top of the page, divided into container and innerbox. We can notice that the edge of the header container and padding does not align but has a certain gap. This gap is actually `header-ascent: 30%`, and the percentage is relative to margin-top. Also, we notice that the header innerbox is actually located at the bottom left corner of the header container, meaning the innerbox defaults to `#set align(left + bottom)`. +5. **Footer:** The Footer is the content at the bottom of the page, divided into container and innerbox. We can notice that the edge of the footer container and padding does not align but has a certain gap. This gap is actually `footer-descent: 30%`, and the percentage is relative to margin-bottom. Also, we notice that the footer innerbox is actually located at the top left corner of the footer container, meaning the innerbox defaults to `#set align(left + top)`. +6. **Place:** The `place` function can achieve absolute positioning, relative to the parent container, without affecting other elements within the parent container. It can take parameters like `alignment`, `dx`, and `dy`, making it suitable for placing decorative elements such as logos. + +Therefore, to apply Typst to create slides, we only need to set + +```typst +#set page( + margin: (x: 0em, y: 2em), + header: align(top)[Header], + footer: align(bottom)[Footer], + header-ascent: 0em, + footer-descent: 0em, +) +#let padding = (x: 4em, y: 0em) +``` + +For example, we have + +```typst +#let container = rect.with(stroke: (dash: "dashed"), height: 100%, width: 100%, inset: 0pt) +#let innerbox = rect.with(fill: rgb("#d0d0d0")) + +#set text(size: 30pt) +#set page( + paper: "presentation-16-9", + margin: (x: 0em, y: 2em), + header: container[#align(top)[#innerbox(width: 100%)[Header]]], + header-ascent: 0em, + footer: container[#align(bottom)[#innerbox(width: 100%)[Footer]]], + footer-descent: 0em, +) +#let padding = (x: 4em, y: 0em) + +#place(top + right)[↑Margin] +#container[ + #place[Padding] + #pad(..padding)[ + #container[ + #innerbox[Content] + ] + ] +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/6127d231-86f3-4262-b7c6-b199d47ae12b) + +## Page Management + +Since using the `set page(..)` command in Typst to modify page parameters creates a new page and cannot modify the current one, Touying chooses to maintain an `s.page-args` member variable and an `s.padding` member variable. Touying applies these parameters only when creating new slides, so users only need to focus on `s.page-args` and `s.padding`. + +For example, the previous example can be transformed into + +```typst +#(s.page-args += ( + margin: (x: 0em, y: 2em), + header: align(top)[Header], + footer: align(bottom)[Footer], + header-ascent: 0em, + footer-descent: 0em, +)) +#(s.padding += (x: 4em, y: 0em)) +``` + +Similarly, if you are not satisfied with the header or footer style of a theme, you can use + +```typst +#(s.page-args.footer = [Custom Footer]) +``` + +to replace it. However, please note that if you replace the page parameters in this way, you need to place it before `#let (slide,) = utils.slides(s)`, or you need to call `#let (slide,) = utils.slides(s)` again. + +:::warning[Warning] + +Therefore, you should not use the `set page(..)` command on your own; instead, you should modify the `s.page-args` member variable internally. + +::: + +In this way, we can also query the current page parameters in real-time through `s.page-args`. This is useful for some functions that need to get margin or the current page's background color, such as `transparent-cover`. This is partly equivalent to the context get rule, and it is actually more convenient to use. + +## Application: Adding a Logo + +Adding a logo to slides is a very common but also a very versatile requirement. The difficulty lies in the fact that the required size and position of the logo often vary from person to person. Therefore, most of Touying's themes do not include configuration options for logos. But with the concepts of page layout mentioned in this section, we know that we can use the `place` function in the header or footer to place a logo image. + +For example, suppose we decide to add the GitHub icon to the metropolis theme. We can implement it like this: + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/octique:0.1.0": * + +#let s = themes.metropolis.register(aspect-ratio: "16-9") +#(s.page-args.header = self => { + // display the original header + utils.call-or-display(self, s.page-args.header) + // place logo at the top-right + place(top + right, dx: -0.5em, dy: 0.3em)[ + #octique("mark-github", color: rgb("#fafafa"), width: 1.5em, height: 1.5em) + ] +}) +#let (init, slide) = utils.methods(s) +#show: init + +#slide(title: [Title])[ + Logo example. +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/055d77e7-5087-4248-b969-d8ef9d50c54b) + +Here, `utils.call-or-display(self, body)` can be used to display `body` as content or a callback function in the form `self => content`. + +## Page Columns + +If you need to divide the page into two or three columns, you can use the `compose` feature provided by the default `slide` function in Touying. The simplest example is as follows: + +```typst +#slide[ + First column. +][ + Second column. +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/a39f88a2-f1ba-4420-8f78-6a0fc644704e) + +If you need to change the way columns are composed, you can modify the `composer` parameter of `slide`. The default parameter is `utils.with.side-by-side(columns: auto, gutter: 1em)`. If we want the left column to occupy the remaining width, we can use + +```typst +#slide(composer: utils.side-by-side.with(columns: (1fr, auto), gutter: 1em))[ + First column. +][ + Second column. +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/aa84192a-4082-495d-9773-b06df32ab8dc) + diff --git a/docs/versioned_docs/version-0.3.2+/progress/_category_.json b/docs/versioned_docs/version-0.3.2+/progress/_category_.json new file mode 100644 index 000000000..f54a7c1f6 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/progress/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Progress", + "position": 11, + "link": { + "type": "generated-index", + "description": "Manage and display progress in Touying, such as counters and sections." + } +} diff --git a/docs/versioned_docs/version-0.3.2+/progress/counters.md b/docs/versioned_docs/version-0.3.2+/progress/counters.md new file mode 100644 index 000000000..5bf50b8bc --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/progress/counters.md @@ -0,0 +1,45 @@ +--- +sidebar_position: 1 +--- + +# Touying Counters + +The states of Touying are placed under the `states` namespace, including all counters. + +## Slide Counter + +You can access the slide counter using `states.slide-counter` and display the current slide number with `states.slide-counter.display()`. + +## Last-Slide Counter + +In some cases, we may need to add an appendix to slides, leading to the requirement to freeze the last-slide counter. Therefore, a second counter is maintained here. + +You can use `states.last-slide-number` to display the number of the last slide before the appendix. + +## Progress + +You can use + +```typst +#states.touying-progress(ratio => ..) +``` + +to show the current progress. + +## Appendix + +You can use + +```typst +// appendix by freezing last-slide-number +#let s = (s.methods.appendix)(self: s) +#let (slide,) = utils.methods(s) + +#slide[ + appendix +] +``` + +syntax to enter the appendix. + +Additionally, `#let s = (s.methods.appendix-in-outline)(self: s, false)` can be used to hide the appendix section from the outline. \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/progress/sections.md b/docs/versioned_docs/version-0.3.2+/progress/sections.md new file mode 100644 index 000000000..0a0140eb0 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/progress/sections.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 2 +--- + +# Touying Sections + +Touying maintains its own sections state to record the sections and subsections of slides. + +## touying-outline + +`#touying-outline(enum-args: (:), padding: 0pt)` is used to display a simple outline. + +## touying-final-sections + +`#states.touying-final-sections(final-sections => ..)` is used to customize the display of the outline. + +## touying-progress-with-sections + +```typst +#states.touying-progress-with-sections((current-sections: .., final-sections: .., current-slide-number: .., last-slide-number: ..) => ..) +``` + +This is the most powerful one, allowing you to build any complex progress display with its functionalities. \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/sections.md b/docs/versioned_docs/version-0.3.2+/sections.md new file mode 100644 index 000000000..329999ec9 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/sections.md @@ -0,0 +1,97 @@ +--- +sidebar_position: 3 +--- + +# Sections and Subsections + +## Structure + +Similar to Beamer, Touying also has the concept of sections and subsections. + +Generally, level 1, level 2, and level 3 headings correspond to section, subsection, and title, respectively, as in the dewdrop theme. + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.dewdrop.register() +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides + += Section + +== Subsection + +=== Title + +Hello, Touying! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/1574e74d-25c1-418f-a84f-b974f42edae5) + +However, often we don't need subsections, and we can use level 1 and level 2 headings to correspond to section and title, as in the university theme. + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.university.register() +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides + += Section + +== Title + +Hello, Touying! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/9dd77c98-9c08-4811-872e-092bbdebf394) + +In fact, we can control this behavior through the `slide-level` parameter of the `slides` function. `slide-level` represents the complexity of the nested structure, starting from 0. For example, `#show: slides.with(slide-level: 2)` is equivalent to the section, subsection, and title structure; while `#show: slides.with(slide-level: 1)` is equivalent to the section and title structure. + +## Table of Contents + +Displaying a table of contents in Touying is straightforward: + +```typst +#import "@preview/touying:0.3.2": * + +#let (init, slides, alert, touying-outline) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides.with(slide-level: 2) + += Section + +== Subsection + +=== Title + +==== Table of contents + +#touying-outline() +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/3cc09550-d3cc-40c2-a315-22ca8173798f) + +Where the definition of `touying-outline()` is: + +```typst +#let touying-outline(enum-args: (:), padding: 0pt) = { .. } +``` + +You can modify the parameters of the internal enum through `enum-args`. + +If you have complex custom requirements for the table of contents, you can use: + +```typst +#states.touying-final-sections(sections => ..) +``` + +As done in the dewdrop theme. \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/start.md b/docs/versioned_docs/version-0.3.2+/start.md new file mode 100644 index 000000000..4d76c3823 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/start.md @@ -0,0 +1,245 @@ +--- +sidebar_position: 2 +--- + +# Getting Started + +Before you begin, make sure you have the Typst environment installed. If not, you can use the [Web App](https://typst.app/) or install the [Typst LSP](https://marketplace.visualstudio.com/items?itemName=nvarner.typst-lsp) and [Typst Preview](https://marketplace.visualstudio.com/items?itemName=mgt19937.typst-preview) plugins for VS Code. + +To use Touying, you just need to include the following in your document: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register() +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide,) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/f5bdbf8f-7bf9-45fd-9923-0fa5d66450b2) + +It's that simple! You've created your first Touying slides. Congratulations! 🎉 + +**Tip:** You can use Typst syntax like `#import "config.typ": *` or `#include "content.typ"` to implement Touying's multi-file architecture. + +**Warning:** The comma in `#let (slide,) = utils.slides(s)` is necessary for the unpacking syntax. + +## More Complex Examples + +In fact, Touying provides various styles for slide writing. You can also use the `#slide[..]` syntax to access more powerful features provided by Touying. + +![image](https://github.com/touying-typ/touying/assets/34951714/fcecb505-d2d1-4e36-945a-225f4661a694) + +Touying offers many built-in themes to easily create beautiful slides. For example, in this case: + +``` +#let s = themes.university.register(aspect-ratio: "16-9") +``` + +you can use the university theme. For more detailed tutorials on themes, you can refer to the following sections. + +```typst +#import "@preview/touying:0.3.2": * +#import "@preview/cetz:0.2.1" +#import "@preview/fletcher:0.4.2" as fletcher: node, edge + +// cetz and fletcher bindings for touying +#let cetz-canvas = touying-reducer.with(reduce: cetz.canvas, cover: cetz.draw.hide.with(bounds: true)) +#let fletcher-diagram = touying-reducer.with(reduce: (arr, ..args) => fletcher.diagram(..args, ..arr)) + +// Register university theme +// You can remove the theme registration or replace other themes +// it can still work normally +#let s = themes.university.register(aspect-ratio: "16-9") + +// Global information configuration +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) + +// Pdfpc configuration +// typst query --root . ./example.typ --field value --one "" > ./example.pdfpc +#let s = (s.methods.append-preamble)(self: s, pdfpc.config( + duration-minutes: 30, + start-time: datetime(hour: 14, minute: 10, second: 0), + end-time: datetime(hour: 14, minute: 40, second: 0), + last-minutes: 5, + note-font-size: 12, + disable-markdown: false, + default-transition: ( + type: "push", + duration-seconds: 2, + angle: ltr, + alignment: "vertical", + direction: "inward", + ), +)) + +// Extract methods +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +// Extract slide functions +#let (slide,) = utils.slides(s) +#show: slides + += Animation + +== Simple Animation + +#slide[ + 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. +] + +== Complex Animation + +#slide(repeat: 3, self => [ + #let (uncover, only, alternatives) = utils.methods(self) + + At subslide #self.subslide, we can + + use #uncover("2-")[`#uncover` function] for reserving space, + + use #only("2-")[`#only` function] for not reserving space, + + #alternatives[call `#only` multiple times \u{2717}][use `#alternatives` function #sym.checkmark] for choosing one of the alternatives. +]) + +== Math Equation Animation + +#slide[ + Touying equation with `pause`: + + #touying-equation(` + f(x) &= pause x^2 + 2x + 1 \ + &= pause (x + 1)^2 \ + `) + + #meanwhile + + Here, #pause we have the expression of $f(x)$. + + #pause + + By factorizing, we can obtain this result. +] + +== CeTZ Animation + +#slide[ + CeTZ Animation in Touying: + + #cetz-canvas({ + import cetz.draw: * + + rect((0,0), (5,5)) + + (pause,) + + rect((0,0), (1,1)) + rect((1,1), (2,2)) + rect((2,2), (3,3)) + + (pause,) + + line((0,0), (2.5, 2.5), name: "line") + }) +] + +== Fletcher Animation + +#slide[ + Fletcher Animation in Touying: + + #fletcher-diagram( + node-stroke: .1em, + node-fill: gradient.radial(blue.lighten(80%), blue, center: (30%, 20%), radius: 80%), + spacing: 4em, + edge((-1,0), "r", "-|>", `open(path)`, label-pos: 0, label-side: center), + node((0,0), `reading`, radius: 2em), + edge((0,0), (0,0), `read()`, "--|>", bend: 130deg), + pause, + edge(`read()`, "-|>"), + node((1,0), `eof`, radius: 2em), + pause, + edge(`close()`, "-|>"), + node((2,0), `closed`, radius: 2em, extrude: (-2.5, 0)), + edge((0,0), (2,0), `close()`, "-|>", bend: -40deg), + ) +] + + += Others + +== Side-by-side + +#slide[ + First column. +][ + Second column. +] + +== Setting + +#slide(setting: body => { + set text(fill: blue) + body +})[ + This slide has blue text. +] + +== Multiple Pages + +#slide[ + #lorem(200) +] + + +// appendix by freezing last-slide-number +#let s = (s.methods.appendix)(self: s) +#let (slide,) = utils.slides(s) + +== Appendix + +#slide[ + Please pay attention to the current slide number. +] +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/fcecb505-d2d1-4e36-945a-225f4661a694) + +Touying offers many built-in themes to easily create beautiful slides. For example, in this case: + +``` +#let s = themes.university.register(aspect-ratio: "16-9") +``` + +you can use the university theme. For more detailed tutorials on themes, you can refer to the following sections. \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/themes/_category_.json b/docs/versioned_docs/version-0.3.2+/themes/_category_.json new file mode 100644 index 000000000..9090a89e8 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/themes/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Themes", + "position": 9, + "link": { + "type": "generated-index", + "description": "One convenient aspect of using Touying is that you can use the themes provided by Touying or create your own themes or templates with the help of Touying." + } +} \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/themes/aqua.md b/docs/versioned_docs/version-0.3.2+/themes/aqua.md new file mode 100644 index 000000000..d3262a40e --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/themes/aqua.md @@ -0,0 +1,199 @@ +--- +sidebar_position: 5 +--- + +# Aqua Theme + +![image](https://github.com/touying-typ/touying/assets/34951714/5f9b3c99-a22a-4f3d-a266-93dd75997593) + +This theme is created by [@pride7](https://github.com/pride7), featuring beautiful backgrounds made with Typst's visualization capabilities. + +## Initialization + +You can initialize it with the following code: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.aqua.register(aspect-ratio: "16-9", lang: "en") +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, outline-slide, focus-slide) = utils.slides(s) +#show: slides +``` + +Where `register` takes parameters: + +- `aspect-ratio`: The aspect ratio of slides, either "16-9" or "4-3", default is "16-9". +- `footer`: Content shown on the right side of the footer, default is `states.slide-counter.display()`. +- `lang`: Language configuration, currently supports `"en"` and `"zh"`, default is `"en"`. + +Aqua theme also provides an `#alert[..]` function, which you can utilize with `#show strong: alert` using `*alert text*` syntax. + +## Color Themes + +Aqua by default uses: + +```typst +#let s = (s.methods.colors)( + self: s, + primary: rgb("#003F88"), + primary-light: rgb("#2159A5"), + primary-lightest: rgb("#F2F4F8"), +``` + +color themes, which you can modify by `#let s = (s.methods.colors)(self: s, ..)`. + +## Slide Function Family + +Aqua theme offers a series of custom slide functions: + +```typst +#title-slide(..args) +``` + +`title-slide` will read information from `self.info` for display. + +--- + +```typst +#let outline-slide(self: none, enum-args: (:), leading: 50pt) +``` + +Display an outline slide. + +--- + +```typst +#slide( + repeat: auto, + setting: body => body, + composer: utils.side-by-side, + section: none, + subsection: none, + // Aqua theme + title: auto, +)[ + ... +] +``` + +A default ordinary slide function with title and footer, where `title` defaults to the current section title. + +--- + +```typst +#focus-slide[ + ... +] +``` + +Used to draw the audience's attention. The background color is `self.colors.primary`. + +--- + +```typst +#new-section-slide(title) +``` + +Start a new section with the given title. + +## `slides` Function + +The `slides` function has parameters: + +- `title-slide`: Default is `true`. +- `outline-slide`: Default is `true`. +- `slide-level`: Default is `1`. + +They can be set via `#show: slides.with(..)`. + +PS: The outline title can be modified via `#(s.outline-title = [Outline])`. + +Additionally, you can disable the automatic inclusion of `new-section-slide` functionality by `#(s.methods.touying-new-section-slide = none)`. + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.aqua.register(aspect-ratio: "16-9", lang: "en") +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, outline-slide, focus-slide) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/eea4df8d-d9fd-43ac-aaf7-bb459864a9ac) + +## Example + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.aqua.register(aspect-ratio: "16-9", lang: "en") +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, outline-slide, focus-slide) = utils.slides(s) +#show: slides + += The Section + +== Slide Title + +#slide[ + #lorem(40) +] + +#focus-slide[ + Another variant with primary color in background... +] + +== Summary + +#align(center + horizon)[ + #set text(size: 3em, weight: "bold", s.colors.primary) + THANKS FOR ALL +] +``` \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/themes/dewdrop.md b/docs/versioned_docs/version-0.3.2+/themes/dewdrop.md new file mode 100644 index 000000000..0aee7bb74 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/themes/dewdrop.md @@ -0,0 +1,269 @@ +--- +sidebar_position: 3 +--- + +# Dewdrop Theme + +![image](https://github.com/touying-typ/touying/assets/34951714/0b5b2bb2-c6ec-45c0-9cea-0af2ed896bba) + +This theme takes inspiration from Zhibo Wang's [BeamerTheme](https://github.com/zbowang/BeamerTheme) and has been modified by [OrangeX4](https://github.com/OrangeX4). + +The Dewdrop theme features an elegantly designed navigation, including two modes: `sidebar` and `mini-slides`. + +## Initialization + +You can initialize it using the following code: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.dewdrop.register( + aspect-ratio: "16-9", + footer: [Dewdrop], + navigation: "mini-slides", + // navigation: "sidebar", + // navigation: none, +) +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, new-section-slide, focus-slide) = utils.slides(s) +#show: slides +``` + +The `register` function takes the following parameters: + +- `aspect-ratio`: The aspect ratio of the slides, either "16-9" or "4-3," defaulting to "16-9." +- `navigation`: The navigation bar style, which can be `"sidebar"`, `"mini-slides"`, or `none`, defaulting to `"sidebar"`. +- `sidebar`: Sidebar navigation settings, defaulting to `(width: 10em)`. +- `mini-slides`: Mini-slides settings, defaulting to `(height: 2em, x: 2em, section: false, subsection: true)`. + - `height`: The height of mini-slides, defaulting to `2em`. + - `x`: Padding on the x-axis for mini-slides, defaulting to `2em`. + - `section`: Whether to display slides after the section and before the subsection, defaulting to `false`. + - `subsection`: Whether to split mini-slides based on subsections or compress them into one line, defaulting to `true`. +- `footer`: Content displayed in the footer, defaulting to `[]`, or it can be passed as a function like `self => self.info.author`. +- `footer-right`: Content displayed on the right side of the footer, defaulting to `states.slide-counter.display() + " / " + states.last-slide-number`. +- `primary`: Primary color, defaulting to `rgb("#0c4842")`. +- `alpha`: Transparency, defaulting to `70%`. + +The Dewdrop theme also provides an `#alert[..]` function, which you can use with `#show strong: alert` using the `*alert text*` syntax. + +## Color Theme + +Dewdrop uses the following default color theme: + +```typst +#let s = (s.methods.colors)( + self: s, + neutral-darkest: rgb("#000000"), + neutral-dark: rgb("#202020"), + neutral-light: rgb("#f3f3f3"), + neutral-lightest: rgb("#ffffff"), + primary: primary, +) +``` + +You can modify this color theme using `#let s = (s.methods.colors)(self: s, ..)`. + +## Slide Function Family + +The Dewdrop theme provides a variety of custom slide functions: + +```typst +#title-slide(extra: none, ..args) +``` + +`title-slide` reads information from `self.info` for display, and you can also pass in an `extra` parameter to display additional information. + +--- + +```typst +#slide( + repeat: auto, + setting: body => body, + composer: utils.side-by-side, + section: none, + subsection: none, + // Dewdrop theme + footer: auto, +)[ + ... +] +``` + +A default slide with navigation and footer, where the footer is what you set. + +--- + +```typst +#focus-slide[ + ... +] +``` + +Used to draw attention, with the background color set to `self.colors.primary`. + +## Special Functions + +```typst +#d-outline(enum-args: (:), list-args: (:), cover: true) +``` + +Displays the current table of contents. The `cover` parameter specifies whether to hide sections in an inactive state. + +--- + +```typst +#d-sidebar() +``` + +An internal function used to display the sidebar. + +--- + +```typst +#d-mini-slides() +``` + +An internal function used to display mini-slides. + +## `slides` Function + +The `slides` function has the following parameters: + +- `title-slide`: Defaults to `true`. +- `outline-slide`: Defaults to `true`. +- `slide-level`: Defaults to `2`. + +You can set these using `#show: slides.with(..)`. + +PS: You can modify the outline title using `#(s.outline-title = [Outline])`. + +And the function of automatically adding `new-section-slide` can be turned off by `#(s.methods.touying-new-section-slide = none)`. + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.dewdrop.register(aspect-ratio: "16-9", footer: [Dewdrop]) +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, new-section-slide, focus-slide) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/09ddfb40-4f97-4062-8261-23f87690c33e) + + +## Example + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.dewdrop.register( + aspect-ratio: "16-9", + footer: [Dewdrop], + navigation: "mini-slides", + // navigation: none, +) +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, new-section-slide, focus-slide) = utils.slides(s) +#show: slides + += Section A + +== Subsection A.1 + +#slide[ + A slide with equation: + + $ x_(n+1) = (x_n + a/x_n) / 2 $ +] + +== Subsection A.2 + +#slide[ + A slide without a title but with *important* infos +] + += Section B + +== Subsection B.1 + +#slide[ + #lorem(80) +] + +#focus-slide[ + Wake up! +] + +== Subsection B.2 + +#slide[ + 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. +] + +// appendix by freezing last-slide-number +#let s = (s.methods.appendix)(self: s) +#let (slide,) = utils.slides(s) + += Appendix + +=== Appendix + +#slide[ + Please pay attention to the current slide number. +] +``` + diff --git a/docs/versioned_docs/version-0.3.2+/themes/metropolis.md b/docs/versioned_docs/version-0.3.2+/themes/metropolis.md new file mode 100644 index 000000000..1b8f88655 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/themes/metropolis.md @@ -0,0 +1,228 @@ +--- +sidebar_position: 2 +--- + +# Metropolis Theme + +![image](https://github.com/touying-typ/touying/assets/34951714/383ceb22-f696-4450-83a6-c0f17e4597e1) + +This theme draws inspiration from Matthias Vogelgesang's [Metropolis beamer](https://github.com/matze/mtheme) theme and has been modified by [Enivex](https://github.com/Enivex). + +The Metropolis theme is elegant and suitable for everyday use. It is recommended to have Fira Sans and Fira Math fonts installed on your computer for the best results. + +## Initialization + +You can initialize it using the following code: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.metropolis.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#let (slide, title-slide, new-section-slide, focus-slide) = utils.slides(s) +#show: slides +``` + +The `register` function takes the following parameters: + +- `aspect-ratio`: The aspect ratio of the slides, either "16-9" or "4-3," defaulting to "16-9." +- `header`: Content displayed in the header, defaulting to `states.current-section-title`, or it can be passed as a function like `self => self.info.title`. +- `footer`: Content displayed in the footer, defaulting to `[]`, or it can be passed as a function like `self => self.info.author`. +- `footer-right`: Content displayed on the right side of the footer, defaulting to `states.slide-counter.display() + " / " + states.last-slide-number`. +- `footer-progress`: Whether to show the progress bar at the bottom of the slide, defaulting to `true`. + +The Metropolis theme also provides an `#alert[..]` function, which you can use with `#show strong: alert` using the `*alert text*` syntax. + +## Color Theme + +Metropolis uses the following default color theme: + +```typst +#let s = (s.methods.colors)( + self: s, + neutral-lightest: rgb("#fafafa"), + primary-dark: rgb("#23373b"), + secondary-light: rgb("#eb811b"), + secondary-lighter: rgb("#d6c6b7"), +) +``` + +You can modify this color theme using `#let s = (s.methods.colors)(self: s, ..)`. + +## Slide Function Family + +The Metropolis theme provides a variety of custom slide functions: + +```typst +#title-slide(extra: none, ..args) +``` + +`title-slide` reads information from `self.info` for display, and you can also pass in an `extra` parameter to display additional information. + +--- + +```typst +#slide( + repeat: auto, + setting: body => body, + composer: utils.side-by-side, + section: none, + subsection: none, + // metropolis theme + title: auto, + footer: auto, + align: horizon, +)[ + ... +] +``` + +A default slide with headers and footers, where the title defaults to the current section title, and the footer is what you set. + +--- + +```typst +#focus-slide[ + ... +] +``` + +Used to draw attention, with the background color set to `self.colors.primary-dark`. + +--- + +```typst +#new-section-slide(short-title: auto, title) +``` + +Creates a new section with the given title. + +## `slides` Function + +The `slides` function has the following parameters: + +- `title-slide`: Defaults to `true`. +- `outline-slide`: Defaults to `true`. +- `slide-level`: Defaults to `1`. + +You can set these using `#show: slides.with(..)`. + +PS: You can modify the outline title using `#(s.outline-title = [Outline])`. + +And the function of automatically adding `new-section-slide` can be turned off by `#(s.methods.touying-new-section-slide = none)`. + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.metropolis.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let s = (s.methods.enable-transparent-cover)(self: s) +#let (init, slide, slides, title-slide, new-section-slide, focus-slide, touying-outline, alert) = utils.methods(s) +#show: init + +#show strong: alert + +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/4ab45ee6-09f7-498b-b349-e889d6e42e3e) + + +## Example + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.metropolis.register(aspect-ratio: "16-9", footer: self => self.info.institution) +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#set text(font: "Fira Sans", weight: "light", size: 20pt) +#show math.equation: set text(font: "Fira Math") +#set strong(delta: 100) +#set par(justify: true) +#show strong: alert + +#let (slide, title-slide, new-section-slide, focus-slide) = utils.slides(s) +#show: slides + += First Section + +#slide[ + A slide without a title but with some *important* information. +] + +== A long long long long long long long long long long long long long long long long long long long long long long long long Title + +#slide[ + A slide with equation: + + $ x_(n+1) = (x_n + a/x_n) / 2 $ + + #lorem(200) +] + += Second Section + +#focus-slide[ + Wake up! +] + +== Simple Animation + +#slide[ + A simple #pause dynamic slide with #alert[alert] + + #pause + + text. +] + +// appendix by freezing last-slide-number +#let s = (s.methods.appendix)(self: s) +#let (slide,) = utils.slides(s) + += Appendix + +#slide[ + Appendix. +] +``` + diff --git a/docs/versioned_docs/version-0.3.2+/themes/simple.md b/docs/versioned_docs/version-0.3.2+/themes/simple.md new file mode 100644 index 000000000..25cf40a0b --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/themes/simple.md @@ -0,0 +1,170 @@ +--- +sidebar_position: 1 +--- + +# Simple Theme + +![image](https://github.com/touying-typ/touying/assets/34951714/83d5295e-f961-4ffd-bc56-a7049848d408) + +This theme originates from [Polylux](https://polylux.dev/book/themes/gallery/simple.html), created by Andreas Kröpelin. + +Considered a relatively straightforward theme, you can use it to create simple slides and freely incorporate features you like. + +## Initialization + +You can initialize it using the following code: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register(aspect-ratio: "16-9", footer: [Simple slides]) +#let s = (s.methods.enable-transparent-cover)(self: s) +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide, title-slide, centered-slide, focus-slide) = utils.slides(s) +#show: slides +``` + +The `register` function takes the following parameters: + +- `aspect-ratio`: The aspect ratio of the slides, either "16-9" or "4-3," defaulting to "16-9." +- `footer`: Content displayed in the footer, defaulting to `[]`, or it can be passed as a function like `self => self.info.author`. +- `footer-right`: Content displayed on the right side of the footer, defaulting to `states.slide-counter.display() + " / " + states.last-slide-number`. +- `background`: Background color, defaulting to white. +- `foreground`: Text color, defaulting to black. +- `primary`: Theme color, defaulting to `aqua.darken(50%)`. + +## Slide Function Family + +The Simple theme provides a variety of custom slide functions: + +```typst +#centered-slide(section: ..)[ + ... +] +``` + +A slide with content centered, and the `section` parameter can be used to create a new section. + +--- + +```typst +#title-slide[ + ... +] +``` + +Similar to `centered-slide`, this is provided for consistency with Polylux syntax. + +--- + +```typst +#slide( + repeat: auto, + setting: body => body, + composer: utils.side-by-side, + section: none, + subsection: none, + // simple theme args + footer: auto, +)[ + ... +] +``` + +A default slide with headers and footers, where the header corresponds to the current section, and the footer is what you set. + +--- + +```typst +#focus-slide(foreground: ..., background: ...)[ + ... +] +``` + +Used to draw attention, it optionally accepts a foreground color (defaulting to `white`) and a background color (defaulting to `auto`, i.e., `self.colors.primary`). + +## `slides` Function + +The `slides` function has the following parameter: + +- `slide-level`: Defaults to `1`. + +You can set it using `#show: slides.with(..)`. + +And the function of automatically adding `new-section-slide` can be turned off by `#(s.methods.touying-new-section-slide = none)`. + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register(aspect-ratio: "16-9", footer: [Simple slides]) +#let s = (s.methods.enable-transparent-cover)(self: s) +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide, title-slide, centered-slide, focus-slide) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/2c599bd1-6250-497f-a65b-f19ae02a16cb) + + +## Example + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.simple.register(aspect-ratio: "16-9", footer: [Simple slides]) +#let (init, slides) = utils.methods(s) +#show: init + +#let (slide, title-slide, centered-slide, focus-slide) = utils.slides(s) +#show: slides + +#title-slide[ + = Keep it simple! + #v(2em) + + Alpha #footnote[Uni Augsburg] #h(1em) + Bravo #footnote[Uni Bayreuth] #h(1em) + Charlie #footnote[Uni Chemnitz] #h(1em) + + July 23 +] + +== First slide + +#slide[ + #lorem(20) +] + +#focus-slide[ + _Focus!_ + + This is very important. +] + += Let's start a new section! + +== Dynamic slide + +#slide[ + Did you know that... + + #pause + + ...you can see the current section at the top of the slide? +] +``` + diff --git a/docs/versioned_docs/version-0.3.2+/themes/university.md b/docs/versioned_docs/version-0.3.2+/themes/university.md new file mode 100644 index 000000000..78073ce13 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/themes/university.md @@ -0,0 +1,222 @@ +--- +sidebar_position: 4 +--- + +# University Theme + +![image](https://github.com/touying-typ/touying/assets/34951714/4095163c-0c16-4760-b370-8adc1cdd7e6c) + +This aesthetically pleasing theme is courtesy of [Pol Dellaiera](https://github.com/drupol). + +## Initialization + +You can initialize the University theme using the following code: + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.university.register(aspect-ratio: "16-9") +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#let (slide, title-slide, focus-slide, matrix-slide) = utils.slides(s) +#show: slides +``` + +The `register` function accepts the following parameters: + +- `aspect-ratio`: Sets the aspect ratio of the slides to "16-9" or "4-3," with the default being "16-9." +- `progress-bar`: Controls whether the progress bar at the top of each slide is displayed, with the default being `true`. +- `footer-columns`: The width of the footer in the bottom three columns, the default is `(25%, 1fr, 25%)`. +- `footer-a`: The first column, default is `self => self.info.author`. +- `footer-b`: Second column, default is `self => if self.info.short-title == auto { self.info.title } else { self.info.short-title }`. +- `footer-c`: third column, default is + +```typst +self => { + h(1fr) + utils.info-date(self) + h(1fr) + states.slide-counter.display() + " / " + states.last-slide-number + h(1fr) +} +``` + +Additionally, the University theme provides an `#alert[..]` function, which you can use with the `#show strong: alert` syntax for emphasizing text with `*alert text*`. + +## Color Theme + +The University theme defaults to the following color theme: + +```typst +#let s = (s.methods.colors)( + self: s, + primary: rgb("#04364A"), + secondary: rgb("#176B87"), + tertiary: rgb("#448C95"), +) +``` + +You can modify this color theme using `#let s = (s.methods.colors)(self: s, ..)`. + +## Slide Function Family + +The University theme provides a series of custom slide functions: + +### Title Slide + +```typst +#title-slide(logo: none, authors: none, ..args) +``` + +The `title-slide` function reads information from `self.info` for display. You can also pass the `logo` parameter and an array-type `authors` parameter. + +### Regular Slide + +```typst +#slide( + repeat: auto, + setting: body => body, + composer: utils.side-by-side, + section: none, + subsection: none, + // university theme + title: none, + subtitle: none, + header: none, + footer: auto, +)[ + ... +] +``` + +The default slide function with a title and footer. The `title` defaults to the current section title, and the footer is set as per your configuration. + +### Focus Slide + +```typst +#focus-slide(background-img: ..., background-color: ...)[ + ... +] +``` + +Used to capture the audience's attention. The default background color is `self.colors.primary`. + +### Matrix Slide + +```typst +#matrix-slide(columns: ..., rows: ...)[ + ... +][ + ... +] +``` + +Refer to the [documentation](https://polylux.dev/book/themes/gallery/university.html). + +## `slides` Function + +The `slides` function has parameters: + +- `title-slide`: Defaults to `true`. +- `slide-level`: Defaults to `1`. + +You can set these parameters using `#show: slides.with(..)`. + +And the function of automatically adding `new-section-slide` can be turned off by `#(s.methods.touying-new-section-slide = none)`. + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.university.register(aspect-ratio: "16-9") +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#let (slide, title-slide, focus-slide, matrix-slide) = utils.slides(s) +#show: slides + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![image](https://github.com/touying-typ/touying/assets/34951714/58971045-0b0d-46cb-acc2-caf766c2432d) + + +## Example + +```typst +#import "@preview/touying:0.3.2": * + +#let s = themes.university.register(aspect-ratio: "16-9") +#let s = (s.methods.info)( + self: s, + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], +) +#let (init, slides, touying-outline, alert) = utils.methods(s) +#show: init + +#let (slide, title-slide, focus-slide, matrix-slide) = utils.slides(s) +#show: slides.with(title-slide: false) + +#title-slide(authors: ([Author A], [Author B])) + += The Section + +== Slide Title + +#slide[ + #lorem(40) +] + +#slide(subtitle: emph[What is the problem?])[ + #lorem(40) +] + +#focus-slide[ + *Another variant with primary color in background...* +] + +#matrix-slide[ + left +][ + middle +][ + right +] + +#matrix-slide(columns: 1)[ + top +][ + bottom +] + +#matrix-slide(columns: (1fr, 2fr, 1fr), ..(lorem(8),) * 9) +``` + diff --git a/docs/versioned_docs/version-0.3.2+/utilities/_category_.json b/docs/versioned_docs/version-0.3.2+/utilities/_category_.json new file mode 100644 index 000000000..07e057cc7 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/utilities/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Utilities", + "position": 12, + "link": { + "type": "generated-index", + "description": "Some convenient utility functions." + } +} \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/utilities/fit-to.md b/docs/versioned_docs/version-0.3.2+/utilities/fit-to.md new file mode 100644 index 000000000..78fca4362 --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/utilities/fit-to.md @@ -0,0 +1,53 @@ +--- +sidebar_position: 2 +--- + +# Fit to Height / Width + +Thanks to [ntjess](https://github.com/ntjess) for the code. + +## Fit to Height + +If you need to make an image fill the remaining slide height, you can try the `fit-to-height` function: + +```typst +#utils.fit-to-height(1fr)[BIG] +``` + +Function definition: + +```typst +#let fit-to-height( + width: none, prescale-width: none, grow: true, shrink: true, height, body +) = { .. } +``` + +Parameters: + +- `width`: If specified, this will determine the width of the content after scaling. So, if you want the scaled content to fill half of the slide width, you can use `width: 50%`. +- `prescale-width`: This parameter allows you to make Typst's layout assume that the given content is to be laid out in a container of a certain width before scaling. For example, you can use `prescale-width: 200%` assuming the slide's width is twice the original. +- `grow`: Whether it can grow, default is `true`. +- `shrink`: Whether it can shrink, default is `true`. +- `height`: The specified height. +- `body`: The specific content. + +## Fit to Width + +If you need to limit the title width to exactly fill the slide width, you can try the `fit-to-width` function: + +```typst +#utils.fit-to-width(1fr)[#lorem(20)] +``` + +Function definition: + +```typst +#let fit-to-width(grow: true, shrink: true, width, body) = { .. } +``` + +Parameters: + +- `grow`: Whether it can grow, default is `true`. +- `shrink`: Whether it can shrink, default is `true`. +- `width`: The specified width. +- `body`: The specific content. \ No newline at end of file diff --git a/docs/versioned_docs/version-0.3.2+/utilities/oop.md b/docs/versioned_docs/version-0.3.2+/utilities/oop.md new file mode 100644 index 000000000..16baf9e7f --- /dev/null +++ b/docs/versioned_docs/version-0.3.2+/utilities/oop.md @@ -0,0 +1,27 @@ +--- +sidebar_position: 1 +--- + +# Object-Oriented Programming + +Touying provides some convenient utility functions for object-oriented programming. + +--- + +```typst +#let call-or-display(self, it) = { + if type(it) == function { + return it(self) + } else { + return it + } +} +``` +Call or display as-is. + +--- + +```typst +#let methods(self) = { .. } +``` +Used to bind self to methods and return, very commonly used. \ No newline at end of file diff --git a/docs/versioned_sidebars/version-0.3.2+-sidebars.json b/docs/versioned_sidebars/version-0.3.2+-sidebars.json new file mode 100644 index 000000000..caea0c03b --- /dev/null +++ b/docs/versioned_sidebars/version-0.3.2+-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/docs/versions.json b/docs/versions.json index cb8c9bda8..ba6b9683e 100644 --- a/docs/versions.json +++ b/docs/versions.json @@ -1,4 +1,5 @@ [ + "0.3.2+", "0.3.x", "0.2.x" ]