Code Monkey home page Code Monkey logo

touying's Introduction

Touying (投影 in chinese, /tóuyǐng/, meaning projection) is a powerful and efficient package for creating presentation slides in Typst. Partial code is inherited from Polylux. Therefore, many concepts and APIs remain consistent with 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.

If you like it, consider giving a star on GitHub. Touying is a community-driven project, feel free to suggest any ideas and contribute.

Book badge GitHub GitHub release (latest by date) GitHub Repo stars Themes badge

Document

Read the document to learn all about Touying.

This documentation is powered by Docusaurus. 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.

Special Features

  1. #pause and #meanwhile Marks document
#slide[
  First
  
  #pause
  
  Second

  #meanwhile

  Third

  #pause

  Fourth
]

image

  1. Dewdrop Theme Navigation Bar document

image

  1. touying-equation Math Equation Animation document

image

  1. touying-reducer Cetz and Fletcher Animations document

image

  1. #show: slides Style and #slide[..] Style

  2. Semi-transparent Cover Mode document

image

Quick start

Before you begin, make sure you have installed the Typst environment. If not, you can use the Web App or the Tinymist Typst and Typst Preview extensions for VS Code.

To use Touying, you only need to include the following code in your document:

#import "@preview/touying:0.4.0": *

#let s = themes.simple.register(aspect-ratio: "16-9")
#let (init, slides) = utils.methods(s)
#show: init

#let (slide, empty-slide) = utils.slides(s)
#show: slides


= Title

== First Slide

Hello, Touying!

#pause

Hello, Typst!

image

It's simple. Congratulations on creating your first Touying slide! 🎉

Tip: You can use Typst syntax like #import "config.typ": * or #include "content.typ" to implement Touying's multi-file architecture.

More Complex Examples

In fact, Touying provides various styles for writing slides. For example, the above example uses first-level and second-level titles to create new slides. However, you can also use the #slide[..] format to access more powerful features provided by Touying.

#import "@preview/touying:0.4.0": *
#import "@preview/cetz:0.2.2"
#import "@preview/fletcher:0.4.3" as fletcher: node, edge
#import "@preview/ctheorems:1.1.2": *

// 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: fletcher.diagram, cover: fletcher.hide)

// 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")

// Set the numbering of section and subsection
#let s = (s.methods.numbering)(self: s, section: "1.", "1.1")

// 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 "<pdfpc-file>" > ./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",
  ),
))

// Theroems configuration by ctheorems
#show: thmrules.with(qed-symbol: $square$)
#let theorem = thmbox("theorem", "Theorem", fill: rgb("#eeffee"))
#let corollary = thmplain(
  "corollary",
  "Corollary",
  base: "theorem",
  titlefmt: strong
)
#let definition = thmbox("definition", "Definition", inset: (x: 1.2em, top: 1em))
#let example = thmplain("example", "Example").with(numbering: none)
#let proof = thmproof("proof", "Proof")

// Extract methods
#let (init, slides, touying-outline, alert) = utils.methods(s)
#show: init

#show strong: alert

// Extract slide functions
#let (slide, empty-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),
  )
]


= Theroems

== Prime numbers

#definition[
  A natural number is called a #highlight[_prime number_] if it is greater
  than 1 and cannot be written as the product of two smaller natural numbers.
]
#example[
  The numbers $2$, $3$, and $17$ are prime.
  @cor_largest_prime shows that this list is not exhaustive!
]

#theorem("Euclid")[
  There are infinitely many primes.
]
#proof[
  Suppose to the contrary that $p_1, p_2, dots, p_n$ is a finite enumeration
  of all primes. Set $P = p_1 p_2 dots p_n$. Since $P + 1$ is not in our list,
  it cannot be prime. Thus, some prime factor $p_j$ divides $P + 1$.  Since
  $p_j$ also divides $P$, it must divide the difference $(P + 1) - P = 1$, a
  contradiction.
]

#corollary[
  There is no largest prime number.
] <cor_largest_prime>
#corollary[
  There are infinitely many composite numbers.
]

#theorem[
  There are arbitrarily long stretches of composite numbers.
]

#proof[
  For any $n > 2$, consider $
    n! + 2, quad n! + 3, quad ..., quad n! + n #qedhere
  $
]


= Others

== Side-by-side

#slide[
  First column.
][
  Second column.
]


== Multiple Pages

#slide[
  #lorem(200)
]


// appendix by freezing last-slide-number
#let s = (s.methods.appendix)(self: s)
#let (slide, empty-slide) = utils.slides(s)

== Appendix

#slide[
  Please pay attention to the current slide number.
]

image

Acknowledgements

Thanks to...

touying's People

Contributors

dependabot[bot] avatar orangex4 avatar pride7 avatar pvelayudhan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

touying's Issues

Is it possible to access the `subslide` number in the footer?

Consider this case:

#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.
])

The slide number is 1 in each case. I would like it to show 1.1, 1.2, 1.3 in the footer, but self.subslide is not accessible within footer(self) = ...

Is there another way to achieve this result?

bookmark handles unproperly in 0.4.0

#import "@preview/touying:0.4.0": *

#let s = themes.university.register()
#let (init, slides) = utils.methods(s)
#show: init

#let (slide, empty-slide) = utils.slides(s)
#show: slides

= Section

== Title 1

#slide[
	1
]

== Title 2

#slide[
	2
]

Hello, Touying!

has no bookmark, while 0.3.3 has.

Page Columns feature

使用 #slide[..][..] 时,有什么方法可以终止当前slide的多列布局回到单列模式?

具体来说,例如

#slide(composer: utils.side-by-side.with(columns: (1fr, 1fr,1fr), gutter: 1em)[
  #rect(height:100%,width:100%,[First column.#linebreak() Part I])
],[
  #rect(height:100%,width:100%,[second column.#linebreak() Part II])
],[
  #rect(height:100%,width:100%,[third column.#linebreak() Part II])
])

其结果如下
Snipaste_2024-03-20_21-04-41

有的时候可能需要,对这张slide 进行总结,这时候如何终止多列的特性,实现红色部分的内容添加?touying 有专门的语法选项控制吗?还是可以通过其他 typst 特性去实现呢?

我尝试使用 #place(...[summary...]) 或者 #box(width:300%,...[sumary...]) ,试图让文本超过第一列的范围,但是结果都不理想。

[Feature Request] : Video support

Many many thanks for this great package 👍

Video inclusion support could be the missing piece of this excellent puzzle.
See for example the multimedia or the media9 Latex packages.

Touying is the best slides package for typst IMHO.
Wish you the best !

`#pause` abnormal when manually setting text size and `list` longer than a page

The minimum reproducing code is attached as follows:

I find in two conditions, the #pause command does not work normally:

  1. When in a pate, #set text(size: ??pt) exists
  2. When the length of the content is longer than a page (overflow to a next page)
#import "@preview/touying:0.3.1": *

// Make the paper dimensions fit for a presentation and the text larger
// Register university theme
// You can remove the theme registration or replace other themes
// it can still work normally
#let s = themes.university.register(s, aspect-ratio: "16-9")

// Global information configuration
#let s = (s.methods.info)(
  self: s,
  title: [Title],
  subtitle: [---Subtitle],
  author: [Some one],
  date: datetime.today(),
  institution: [Beijing],
)

// 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



#slide(
  title: [Title here, this page is ok]
)[
  - item 1 #pause
  - item 2 #pause
  - item 3
]

#slide(
  title: [Title here, this page does not \#pause normally]
)[
  #set text(size:25pt)
  - item 1 #pause
  - item 2 #pause
  - item 3
]

#slide(
  title: [Title here, this page is ok]
)[
  - item 1 #pause
  - item 2 #pause
  - item 3 #pause
  - item 4 #pause
  - item 5 #pause
  - item 6 #pause
  - item 7 #pause
  - item 8 #pause
  - item 9 #pause
  - item 10 #pause
  - item 11 #pause
  - item 12
]


#slide(
  title: [Title here, this page does not \#pause normally]
)[
  - item 1 #pause
  - item 2 #pause
  - item 3 #pause
  - item 4 #pause
  - item 5 #pause
  - item 6 #pause
  - item 7 #pause
  - item 8 #pause
  - item 9 #pause
  - item 10 #pause
  - item 11 #pause
  - item 12 #pause
  - item 13 #pause
]

Regression: footnotes doesn't appear since 0.3.0

Footnotes on the simple theme example doesn't render since v0.3.0.

v0.3.0

v0 3 0-slide

v0.2.1

v0 2 1-slide

Minimal reproducible example
// #import "@preview/touying:0.2.1": *
#import "@preview/touying:0.3.0": *

#let s = themes.simple.register(s, aspect-ratio: "16-9", footer: [Simple slides])
#let s = (s.methods.enable-transparent-cover)(self: s)
#let (init, slide, slides, title-slide, centered-slide, focus-slide) = utils.methods(s)
#show: init

#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
]

#slide[
  == First slide

  #lorem(20)
]

#focus-slide[
  _Focus!_

  This is very important.
]

#centered-slide(section: [Let's start a new section!])

#slide[
  == Dynamic slide
  Did you know that...

  #pause
  ...you can see the current section at the top of the slide?
]

Maintain consistency aross different themes

Would it be possible to keep all themes compatible with each other? Currently different themes are implemented in different ways (variable names, function def, etc.) and user can not switch from one theme to another by changing the theme name only. It would be preferrable to define common template for the slides structure and maintain the consistency, just like how LaTeX/Beamer did it.

Outline does not display more than 4 sections

When adding more than 4 sections, the outline does only display the last 4 sections. Also, the typst console shows the warning layout did not converge within 5 attempts with the hint to check if any states or queries are updating themselves.

To reproduce:

#import "@preview/touying:0.2.0": *

#let s = themes.metropolis.register(s, 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, title-slide, new-section-slide, focus-slide, touying-outline) = utils.methods(s)
#show: init

#title-slide(extra: [Extra])

#slide(title: [Table of contents])[
  #touying-outline()
]

#new-section-slide[1]
#new-section-slide[2]
#new-section-slide[3]
#new-section-slide[4]
#new-section-slide[5]

With the code above, the outline shows four entries: 2,3,4,5

The same happens with the dewdrop theme. See MWE:

#import "@preview/touying:0.2.0": *

#let s = themes.dewdrop.register(
  s,
  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 s = (s.methods.enable-transparent-cover)(self: s)
// #let s = (s.methods.appendix-in-outline)(self: s, false)
#let (init, slide, title-slide, touying-outline) = utils.methods(s)
#show: init

#title-slide()

#slide[
  == Outline
  
  #touying-outline(cover: false)
]

#slide(section: [1])[]
#slide(section: [2])[]
#slide(section: [3])[]
#slide(section: [4])[]
#slide(section: [5])[]

文档笔误

中文文档 External Tools - pdfpc 一栏有笔误,但不影响阅读
image
第二段“虽然您可以手动编写此它”
版本如图

typst include dont work

I have following snippets:

#import "@preview/touying:0.2.1": *

#let s = themes.university.register(s, aspect-ratio: "16-9")
#let s = (s.methods.info)(
  self: s,
  title: [C语言程序设计],
  // subtitle: [],
  author: [Author],
  date: datetime.today(),
  institution: [Institute],
)
#let (init, slide, slides, title-slide, focus-slide, matrix-slide, touying-outline, alert) = utils.methods(s)
#show: init

#show: slides

#include "content.typ"

content.typ:

= title

== slide1

bla

== slide2

bla

As if it don't work. What wrong with me?

Show how to change global settings

I am interested in changing the fontsize globally. I figured our how to do this, relying on the "simple" coding style with #slides:

#let my_template(body) = {
  set text(1.1em)
  slides(body)
}

#show: my_template

I am however not sure if this is the best way. I am also uncertain about how to do with if I was using #slides instead, as I get the error "only element functions can be used in set rules" when I do the following:

#set slide(settings: body=>{
  set text(1.1em)
  body
})

A section in the docs on "How to change global settings" or something to that effect would be great ^_^

Weird behavior of outline slide

In the current version (version 0.3.3) of dewdrop theme, if there are too many sections to be packed into a single outline slide, it seem that each of the slide of the outline create a new section/subsection, which is not desired. Is there any quick fix to that?

Section, subsections and slide title as header level

I know that we can use H1 and H2 header levels like this to organize a presentation :

= Section
== Slide title

But is it possible to segment the presentation using H1,H2 and H3 header levels like this :

= Section
== Subsection
=== Slide title

It could make conversion from other format (I'm using obsidian+ pandoc export) much easier.

Is it possible to set slide titles by level-2 headings but create slides with `#slide` function?

Hi! Thanks for your great package.

I've learnt that there are two modes to create packages. In one way, we use #slide to create slides and put the title in the argument title. In the other way, we show the document with #slides and use headings to create slides.

However, I wonder whether a third way is possible. That is to set sections, subsections, and titles with headings (of levels 1, 2, and 3 respectively), but they do not create any slides. Instead, we still use #slide to create slides. By this practice, we can leave a clear structure in the document. And when we need to create several slides with a same title, we don't need to type the title repeatedly.

For example

= Section 1

#new-section-slide[
  Additional content
] // -> A section slide

== Slide A

#slide[
  Some content
] // -> A slide with title "Slide A" and content "Some content".

#slide[
  Some other content
] // -> Another slide with title "Slide A" and content "Some content".

Contents outside the range of #slide are ignored.

Proposal: custom types for touying

Hi,

you did an impressive job to make the OOP work in typst. I wonder if the touying syntax would become easier once typst implements custom types? Have you had a look at the blog post?

Using `extra` argument properly for #title-slide

Hello,

Thanks for the package. I'm wondering how to properly make use of the extra parameter for #title-slide, specifically with the dewdrop theme.

The code below produces three slides:

  1. A title slide missing the extra information, (which I don't want)
  2. An outline slide
  3. A title slide containing the extra information (which I do want)

Ideally, I'd just have slide 3, then slide 1.

#import "@preview/touying:0.3.2": *

#let s = themes.dewdrop.register(
  aspect-ratio: "16-9",
  footer: [Dewdrop],
  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

#title-slide(extra: "Extra")

Sorry, I'm not very experienced with OOP!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.