From: moo Date: Tue, 2 Jun 2026 04:09:06 +0000 (-0700) Subject: first commit X-Git-Url: https://git.taranathan.com/?a=commitdiff_plain;h=2948ec58fbc6cbe1f135b18c6a62e07998907f4b;p=robotics-touying.git first commit --- 2948ec58fbc6cbe1f135b18c6a62e07998907f4b diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..05dae4c --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,259 @@ +# Touying - AI Coding Agent Instructions + +## Project Overview + +Touying is a Typst package for creating presentation slides. It is a powerful alternative to LaTeX Beamer with better performance, achieved by avoiding `counter` and `context` for `#pause` animations. + +## Repository Layout + +``` +lib.typ # Entry point — re-exports src/exports.typ +src/ + core.typ # Animation engine, slide rendering + utils.typ # Shared helpers (merge-dicts, display-current-heading, …) + configs.typ # config-common, config-colors, config-page, config-info, … + exports.typ # Public API surface + components.typ # Reusable slide components (cols, …) +themes/ # 6 built-in themes: simple, metropolis, dewdrop, university, aqua, stargazer +examples/ # Theme usage examples (excluded from package) +tests/ + features/ # Feature regression tests (test.typ + ref/*.png) + themes/ # Theme regression tests + examples/ # Full-presentation tests +typst.toml # Package manifest (name, version, compiler constraint) +``` + +## Development Workflow + +### Tools + +Three tools must be available in your environment (all installed by `.github/workflows/copilot-setup-steps.yml`): + +| Tool | Command | Purpose | +|------|---------|---------| +| Typst CLI | `typst` | Compile `.typ` files | +| tytanic | `tt` | Visual regression test runner | +| typstyle | `typstyle` | Official Typst code formatter | + +### Testing with tytanic + +```bash +# Run the full test suite (compares rendered PNGs against ref/ images) +tt run + +# Run only a subset of tests +tt run tests/features/animation + +# Update reference images after intentional visual changes +tt update + +# List all tests +tt list +``` + +- tytanic automatically locates the project root via `typst.toml` +- Test output goes to `tests/**/out/`, diffs to `tests/**/diff/` +- Reference images are committed in `tests/**/ref/` +- PPI for reference images: 72 (set in `typst.toml` under `[tool.tytanic]`) + +**When to run `tt update`**: After making intentional visual changes (e.g., layout, theme colors), regenerate the reference images with `tt update` and commit the updated `ref/*.png` files. + +### Formatting with typstyle + +**Always format modified `.typ` files before finalising a PR.** The CI enforces this via `git diff --exit-code`. + +```bash +# Format one or more files in-place +typstyle -i src/core.typ src/utils.typ + +# Format an entire directory recursively +typstyle -i themes/ + +# Format all .typ files in the project +typstyle -i src/ themes/ tests/ +``` + +### Compiling a single file (quick check) + +```bash +# No build step required — Touying is a pure Typst package +typst compile --root . tests/features/animation/test.typ /tmp/out.pdf +``` + +## Typst Language Essentials + +### Syntax Modes + +| Mode | Trigger | Example | +|------|---------|---------| +| Markup (default) | — | `*bold*`, `_italic_`, `= Heading` | +| Code | `#` prefix | `#let x = 1`, `#if cond { … }` | +| Math | `$…$` | `$x^2 + y$` | + +> **Always use Typst's native math syntax**, not LaTeX. Typst math is more intuitive. + +### Naming: kebab-case only + +All identifiers (variables, functions, parameters) use **kebab-case**: + +```typst +#let my-variable = 42 +#let calculate-sum(a, b) = a + b +``` + +snake_case, camelCase, and PascalCase are **prohibited**. + +### Reserved identifiers to avoid shadowing + +Do not bind variables or parameters to Typst built-in names. Key ones to avoid: + +- **Types**: `none`, `auto`, `bool`, `int`, `float`, `str`, `content`, `function`, `array`, `dictionary`, `color`, `length`, `ratio`, `angle`, `stroke`, `alignment`, `direction` +- **Layout**: `columns`, `grid`, `table`, `stack`, `box`, `block`, `place`, `align`, `pad`, `measure`, `layout`, `repeat` +- **Text/lists**: `text`, `par`, `list`, `enum`, `item`, `quote`, `raw`, `strong`, `emph` +- **Document**: `document`, `page`, `heading`, `outline`, `figure`, `footnote` +- **Graphics**: `math`, `rect`, `circle`, `polygon`, `rotate`, `scale`, `fill`, `gradient` +- **I/O**: `read`, `include`, `image`, `link`, `ref`, `cite` + +When wrapping these, use a `touying-` prefix: `touying-grid`, `touying-table`. + +### Pure functions & caching + +Typst functions are **pure** — they cannot mutate external state: + +```typst +// ✗ Invalid: cannot push to an external array inside a function +// ✗ Invalid: cannot assign to an external variable + +// ✓ Return new values instead +#let add-item(items, new) = items + (new,) +``` + +Typst automatically **caches** function call results by input. Avoid creating many tiny functions with trivial bodies — inline code is usually preferable to prevent cache bloat. + +## Key API Patterns + +### Slide creation + +```typst +// Heading-based (preferred) += Section // section slide +== Subsection // subsection slide +=== Slide title // content slide + +// Explicit function call +#slide[Content] +#slide(composer: (1fr, 1fr))[Left column][Right column] +``` + +### Animation + +```typst +#pause // incremental reveal +#meanwhile // parallel track with #pause +#uncover("2-")[content] // visible from subslide 2 onward +#only("1,3")[content] // visible only on subslides 1 and 3 +#alternatives[Option A][Option B] + +// Callback style (access self.subslide) +#slide(self => { + let (uncover, only, alternatives) = utils.methods(self) + uncover("2-")[Revealed on 2+] +}) +``` + +### Configuration + +```typst +#show: simple-theme.with( + aspect-ratio: "16-9", + config-info(title: [Title], author: [Author]), + config-colors(primary: blue), + config-common(handout: false), +) + +// Per-slide config override +#slide( + config: utils.merge-dicts( + config-colors(primary: red), + config-common(handout: true), + ) +)[Content] +``` + +Configuration functions: +- `config-colors` — color scheme +- `config-common` — global flags (`handout`, `frozen-counters`, `show-only-notes`, …) +- `config-info` — document metadata (title, author, date, …) +- `config-methods` — animation method overrides +- `config-page` — page layout + +### External package integration (touying-reducer) + +```typst +// CeTZ +#let cetz-canvas = touying-reducer.with( + reduce: cetz.canvas, + cover: cetz.draw.hide.with(bounds: true), +) +#cetz-canvas({ + import cetz.draw: * + rect((0,0), (5,5)) + (pause,) + circle((2.5,2.5), radius: 1) +}) + +// Fletcher +#let fletcher-diagram = touying-reducer.with( + reduce: fletcher.diagram, + cover: fletcher.hide, +) +``` + +### Speaker notes + +```typst +#speaker-note[ + + Remind audience of previous slide + + Key takeaway: … +] +``` + +## Documentation Standard + +Use `///` docstrings for all public functions: + +```typst +/// One-line description. +/// +/// Example: +/// ```typst +/// #my-fn(arg1: value) +/// ``` +/// +/// - arg1 (str): Description. +/// - arg2 (int | none): Optional count, defaults to `none`. +/// +/// -> content +``` + +Types use Typst names (`str`, `int`, `content`, `function`, …); union types use `|`. + +## Special Heading Labels + +Touying recognises these heading labels for slide control: + +| Label | Effect | +|-------|--------| +| `` | Hide slide completely | +| `` | Skip slide in output | +| `` | No slide number | +| `` | Exclude from outline | +| `` | No PDF bookmark | +| `` | Show only in handout mode | + +## Performance Notes + +- Avoid `counter` and `context` inside animation logic (causes recompilation). +- Use `touying-reducer` for external animated content (CeTZ, Fletcher, …). +- Prefer functional composition over mutable state. +- Only extract helpers into named functions when the caching benefit is real. \ No newline at end of file diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 0000000..c58372b --- /dev/null +++ b/.github/workflows/copilot-setup-steps.yml @@ -0,0 +1,48 @@ +name: "Copilot Setup Steps" + +# Automatically run the setup steps when they are changed to allow for easy validation, +# and allow manual testing through the repository's "Actions" tab. +on: + workflow_dispatch: + push: + paths: + - .github/workflows/copilot-setup-steps.yml + pull_request: + paths: + - .github/workflows/copilot-setup-steps.yml + +jobs: + # The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot. + copilot-setup-steps: + runs-on: ubuntu-latest + + permissions: + contents: read + + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Install the Typst CLI (used for compiling .typ files and running tests) + - name: Setup Typst + uses: typst-community/setup-typst@v4 + + # Install Rust toolchain (needed by cargo-binstall and tytanic) + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + + # cargo-binstall provides fast binary installation without full compilation + - name: Install cargo-binstall + uses: taiki-e/install-action@v2 + with: + tool: cargo-binstall + + # tytanic (tt) is the visual regression test runner for Touying + # Pinned to the same version used in test.yml CI + - name: Install tytanic + run: cargo binstall tytanic@0.3.3 -y + + # typstyle is the official Typst code formatter + # Usage: typstyle -i file1.typ file2.typ dir/ + - name: Install typstyle + run: cargo binstall typstyle -y diff --git a/.github/workflows/docs-preview.yml b/.github/workflows/docs-preview.yml new file mode 100644 index 0000000..3be6214 --- /dev/null +++ b/.github/workflows/docs-preview.yml @@ -0,0 +1,154 @@ +name: Docs Preview + +on: + pull_request: + types: [opened, synchronize, reopened, closed] + paths: + - "docs/**" + +# Build runs share one concurrency group and can cancel each other when a new +# commit arrives. Cleanup (PR closed) uses a distinct group so it is never +# cancelled by an in-progress build for the same PR. +concurrency: + group: >- + docs-preview-${{ github.event.number }}-${{ + github.event.action == 'closed' && 'cleanup' || 'build' + }} + cancel-in-progress: true + +permissions: + contents: write # push to gh-pages branch + pull-requests: write # post / update the preview comment + +jobs: + preview: + name: Deploy Docs Preview + runs-on: ubuntu-latest + + steps: + # ── 1. Check out this (touying) repo at the workspace root ───────────── + # The root checkout establishes GITHUB_TOKEN credentials so that + # rossjrw/pr-preview-action can push to *this* repo's gh-pages branch. + - name: Checkout touying (PR branch) + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # ── 2. Clone the Docusaurus website repo ─────────────────────────────── + # We clone it without initialising its submodule because we are about to + # replace the submodule directory with the current PR's content anyway. + - name: Checkout website repo + if: github.event.action != 'closed' + uses: actions/checkout@v4 + with: + repository: touying-typ/touying-typ.github.io + path: website + submodules: false + + # ── 3. Inject this PR's touying content into the website tree ────────── + # The website scripts expect: + # website/touying/docs/en/** (hand-written docs) + # website/touying/docs/zh/** (Chinese docs) + # website/touying/src/** (Typst sources – for generate-docs.py) + # website/touying/themes/** (theme files – for generate-docs.py) + # We rsync everything from the touying root except .git and the website/ + # checkout directory itself to avoid recursion. + - name: Inject PR docs into website + if: github.event.action != 'closed' + run: | + mkdir -p website/touying + rsync -a --exclude='.git' --exclude='website' . website/touying/ + + # ── 4. Set up the Node.js environment ───────────────────────────────── + - name: Set up Node.js + if: github.event.action != 'closed' + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: website/package-lock.json + + # ── 5. Install Typst (required by generate-images.py) ────────────────── + - name: Install Typst + if: github.event.action != 'closed' + uses: typst-community/setup-typst@v4 + + # ── 6. Install Python dependencies (Pillow for generate-images.py) ───── + - name: Install Python dependencies + if: github.event.action != 'closed' + run: pip install Pillow + + # ── 7. Install Node dependencies ─────────────────────────────────────── + - name: Install Node dependencies + if: github.event.action != 'closed' + working-directory: website + run: npm ci + + # ── 8. Run the website's own doc-preparation pipeline ───────────────── + - name: Copy docs from touying into website structure + if: github.event.action != 'closed' + working-directory: website + run: npm run copy-docs + + - name: Generate API reference documentation + if: github.event.action != 'closed' + working-directory: website + run: npm run generate-docs + + - name: Generate slide preview images + if: github.event.action != 'closed' + id: generate-images + working-directory: website + run: npm run generate-images + continue-on-error: true + + - name: Warn if slide image generation failed + if: steps.generate-images.outcome == 'failure' + run: | + echo "::warning::Slide preview image generation failed. The docs preview will be deployed without generated slide images. Check the 'Generate slide preview images' step log for details." + + # ── 9. Patch Docusaurus config for PR preview ───────────────────────── + # The website navbar/footer may contain hardcoded links (e.g. /docs/start, + # /docs/dynamic/simple) that don't exist in every PR's docs structure. + # Downgrading onBrokenLinks from 'throw' to 'warn' prevents the build from + # failing over such link drift while still making broken links visible in + # the build log. + - name: Patch broken-links setting for PR preview + if: github.event.action != 'closed' + working-directory: website + run: | + for f in docusaurus.config.js docusaurus.config.ts docusaurus.config.mjs; do + if [ -f "$f" ]; then + sed -i "s/onBrokenLinks:[[:space:]]*['\"]throw['\"]/onBrokenLinks: 'warn'/g" "$f" + echo "Patched onBrokenLinks in $f" + break + fi + done + + # ── 10. Build the Docusaurus site ────────────────────────────────────── + # The touying repo is hosted at https://touying-typ.github.io/touying/ + # so PR previews live under /touying/pr-preview/pr-NNN/. + # We pass this as DOCUSAURUS_BASE_URL so that Docusaurus sets the + # correct href and all asset / link paths resolve properly. + - name: Build website + if: github.event.action != 'closed' + working-directory: website + run: npm run build + env: + DOCUSAURUS_BASE_URL: /touying/pr-preview/pr-${{ github.event.number }}/ + + # ── 10. Deploy preview (or clean up on PR close) ──────────────────────── + # rossjrw/pr-preview-action: + # - On open/sync/reopen: pushes build/ to the gh-pages branch under + # pr-preview/pr-NNN/ and posts a comment with the preview URL. + # - On close: removes pr-preview/pr-NNN/ from gh-pages and updates + # the comment. + # + # Preview URL: https://touying-typ.github.io/touying/pr-preview/pr-NNN/ + - name: Deploy / clean-up preview + uses: rossjrw/pr-preview-action@v1 + with: + source-dir: website/build + preview-branch: gh-pages + umbrella-dir: pr-preview + action: auto diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..362e359 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,51 @@ +name: Test +on: + push: + pull_request: + +jobs: + tests: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + + - name: Install cargo-binstall + uses: taiki-e/install-action@v2 + with: + tool: cargo-binstall + + - name: Install tytanic + run: cargo binstall tytanic@0.3.3 -y + + - name: Setup typst + uses: typst-community/setup-typst@v4 + + - name: Run test suite + run: tt run + + - name: Archive diffs + uses: actions/upload-artifact@v4 + if: always() + with: + name: artifacts + path: | + tests/**/diff/*.png + tests/**/out/*.png + tests/**/ref/*.png + retention-days: 5 + + typstyle: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Run typstyle + uses: typstyle-rs/typstyle-action@main + - name: Check for changes + # Fails the CI job if typstyle modified any files. + # This ensures developers format their code before merging. + run: git diff --exit-code diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6048d23 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/local + +.DS_Store + +*.pdf +*.pdfpc +nohup.out diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..446f1e2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2026 OrangeX4 +Copyright (c) 2026 zral0kh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..db72228 --- /dev/null +++ b/README.md @@ -0,0 +1,337 @@ +# ![Touying logo - a presentation slides package for Typst](https://github.com/user-attachments/assets/58a91b14-ae1a-49e2-a3e7-5e3a148e2ba5) + +[Touying](https://github.com/touying-typ/touying) (投影 in Chinese, /tóuyǐng/, meaning projection) is a user-friendly, powerful, and efficient package for creating presentation slides in [Typst](https://typst.app/). + +If you like it, consider [giving a star ⭐ on GitHub](https://github.com/touying-typ/touying). Touying is a community-driven project — feel free to suggest ideas and contribute! + +[![Typst Universe](https://img.shields.io/badge/dynamic/xml?url=https%3A%2F%2Ftypst.app%2Funiverse%2Fpackage%2Ftouying&query=%2Fhtml%2Fbody%2Fdiv%2Fmain%2Fdiv%5B2%5D%2Faside%2Fsection%5B2%5D%2Fdl%2Fdd%5B3%5D&logo=typst&label=universe&color=%2339cccc)](https://typst.app/universe/package/touying) +[![Book badge](https://img.shields.io/badge/docs-book-green)](https://touying-typ.github.io/) +[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/touying-typ/touying) +[![Ask Zread for AI-assisted help with Touying](https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff)](https://zread.ai/touying-typ/touying) +[![Gallery badge](https://img.shields.io/badge/demo-gallery-red)](https://github.com/touying-typ/touying/wiki) +![GitHub License](https://img.shields.io/github/license/touying-typ/touying) +![GitHub release (latest by date)](https://img.shields.io/github/v/release/touying-typ/touying) +![GitHub Repo stars](https://img.shields.io/github/stars/touying-typ/touying) +![Themes badge](https://img.shields.io/badge/themes-6-aqua) + + +## Why Touying? + +- **Beautiful themes** — [built-in themes](https://touying-typ.github.io/themes/) like Simple, Metropolis, Dewdrop, University, Aqua, Stargazer and [diverse themes on Typst Universe](https://typst.app/universe/search/?q=touying) +- **Fast** — Typst compiles in milliseconds. Live previews update as you type, giving you the instant feedback. +- **Rich animations** — `#pause`, `#meanwhile`, math equation animations, CeTZ & Fletcher support +- **Heading-based slides** — write presentations like a document, no boilerplate +- **Speaker notes** — dual-screen support via tools like PowerPoint, HTML or pympress +- **Export** — Builtin PDF export, PPTX and HTML via [touying-exporter](https://github.com/touying-typ/touying-exporter) +- **Correct bookmarks** — proper PDF outline and page numbers out of the box + +## Documents & Help + +- [Full documentation and references](https://touying-typ.github.io/) (English & Chinese) +- [Ask DeepWiki](https://deepwiki.com/touying-typ/touying) or [Ask Zread](https://zread.ai/touying-typ/touying) for AI-assisted help +- [Gallery](https://github.com/touying-typ/touying/wiki) — slides made by the community +- [Universe](https://typst.app/universe/search/?q=touying) — Diverse touying themes on Typst Universe +- [Share slides instantly on GitHub](https://gistd.myriad-dreamin.com/touying-typ/touying/blob/main/examples/simple.typ?g-mode=slide) with [gistd](https://github.com/Myriad-Dreamin/gistd) or [export](https://github.com/touying-typ/touying-exporter) slides to PPTX and HTML formats and show presentation [online](https://touying-typ.github.io/touying-template/). + + +## Quick Start + +Make sure you have [Typst](https://typst.app/) installed, or use the [Web App](https://typst.app/) / [Tinymist for VS Code](https://marketplace.visualstudio.com/items?itemName=myriad-dreamin.tinymist). + +```typst +#import "@preview/touying:0.7.3": * +#import themes.simple: * + +#show: simple-theme.with(aspect-ratio: "16-9") + += Title + +== First Slide + +Hello, Touying! + +#pause + +Hello, Typst! +``` + +![Screenshot of a simple Touying slide showing Hello Touying and Hello Typst](https://github.com/touying-typ/touying/assets/34951714/f5bdbf8f-7bf9-45fd-9923-0fa5d66450b2) + +Congratulations on creating your first Touying slide! 🎉 + + +## Animations + +Touying supports incremental reveal with `#pause` and `#meanwhile`, math equation animations, and integrations with CeTZ and Fletcher: + +| Math equations | CeTZ & Fletcher | +|:---:|:---:| +| ![math animation](https://github.com/touying-typ/touying/assets/34951714/8640fe0a-95e4-46ac-b570-c8c79f993de4) | ![cetz fletcher animation](https://github.com/touying-typ/touying/assets/34951714/9ba71f54-2a5d-4144-996c-4a42833cc5cc) | + +For the full feature set — cover mode, callback-style animations, `#uncover`, `#only`, `#alternatives` — see the [documentation](https://touying-typ.github.io/docs/tutorials/dynamic/simple). + + +## Full Example + +For a comprehensive example showcasing university theme, theorems, CeTZ/Fletcher animations, speaker notes, and more. You can also use the `#slide[..]` format to access more powerful features provided by Touying. + +```typst +#import "@preview/touying:0.7.3": * +#import themes.university: * +#import "@preview/cetz:0.5.0" +#import "@preview/fletcher:0.5.8" as fletcher: node, edge +#import "@preview/numbly:0.1.0": numbly +#import "@preview/theorion:0.6.0": * +#import cosmos.clouds: * +#show: show-theorion + +// 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) + +#show: university-theme.with( + aspect-ratio: "16-9", + // align: horizon, + // config-common(handout: true), + config-common(frozen-counters: (theorem-counter,)), // freeze theorem counter for animation + config-info( + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], + logo: emoji.school, + ), +) + +#set heading(numbering: numbly("{1}.", default: "1.1")) + +#title-slide() + +== Outline + +#components.adaptive-columns(outline(title: none, indent: 1em)) + += Animation + +== Simple Animation + +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. + +#speaker-note[ + + This is a speaker note. + + You won't see it unless you use `config-common(show-notes-on-second-screen: right)` +] + + +== Complex Animation + +At subslide #touying-fn-wrapper((self: none) => str(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. + + +== Callback Style 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 + +Equation with `pause`: + +$ + 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 + +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 + +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), +) + + += Theorems + +== 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(title: "Euclid")[ + There are infinitely many primes. +] +#pagebreak(weak: true) +#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. +] +#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 + $ +] + + += Others + +== Multiple columns + +#cols[ + First column. +][ + Second column. +] + +== Multiple columns with equal height blocks + +#cols(columns: (1fr, 1fr), gutter: 1em)[ + #emph-block[ + First column with equal height: #lorem(10) + #lazy-v(1fr) + ] +][ + #emph-block[ + Second column with equal height: : #lorem(15) + #lazy-v(1fr) + ] +] + + +== Multiple Pages + +#lorem(200) + + +#show: appendix + += Appendix + +== Appendix + +Please pay attention to the current slide number. +``` + +![Screenshot of a full example using the university theme with animations and theorems](https://github.com/user-attachments/assets/b1dfc4d9-e263-46ff-8588-a0635870e370) + + +## Acknowledgements + +Thanks to... + +- [@andreasKroepelin](https://github.com/andreasKroepelin) for the `polylux` package +- [@zral0kh](https://github.com/zral0kh) for the waypoint feature and many improvements +- [@enklht](https://github.com/enklht) for many fixes and improvements +- [@Enivex](https://github.com/Enivex) for the `metropolis` theme +- [@drupol](https://github.com/drupol) for the `university` theme +- [@pride7](https://github.com/pride7) for the `aqua` theme +- [@Coekjan](https://github.com/Coekjan) and [@QuadnucYard](https://github.com/QuadnucYard) for the `stargazer` theme +- [@ntjess](https://github.com/ntjess) for contributing to `fit-to-height`, `fit-to-width` and `cover-with-rect` + + +## Poster + +![Touying poster example](https://github.com/user-attachments/assets/e1ddb672-8e8f-472d-b364-b8caed1da16b) + +[View Code](https://github.com/touying-typ/touying-poster) + +## Star History + + + + + + Star History Chart + + \ No newline at end of file diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..8452734 --- /dev/null +++ b/changelog.md @@ -0,0 +1,473 @@ +# Changelog + +## v0.7.3 + +### Minor Breaking Changes + +- **feat!: always attach `#speaker-note[]` to the previous slide & default `receive-body-for-new-*-slide-fn` to `false`** ([#354](https://github.com/touying-typ/touying/pull/354)) + - `#speaker-note[]` now always attaches to the **slide above it**, regardless of how that slide was created (explicit slide calls, heading-triggered section slides, or normal content slides). This eliminates the common pitfall where a `#speaker-note[]` placed after a slide would silently create an unwanted empty "ghost" slide. + - `receive-body-for-new-section-slide-fn` and its variants are now **defaulted to `false`** (previously `true`). + +### Migration Guide + +If you relied on content after `= Section` headings being absorbed into the section slide body, explicitly set `receive-body-for-new-section-slide-fn: true` in your `config-common(...)`. + +### Features + +- feat: `item-by-item-fn` and presets for it ([#347](https://github.com/touying-typ/touying/pull/347)) +- feat: improved `custom-progressive-outline` and new `section-relationship` and some other things ([#345](https://github.com/touying-typ/touying/pull/345)) +- feat: better lazy-layout for mixed layouts ([#355](https://github.com/touying-typ/touying/pull/355)) +- feat: add `cols` as alias of `side-by-side` and export some components `cols`, `lazy-xxx` to outside ([#356](https://github.com/touying-typ/touying/pull/356)) +- theme(metropolis): add outline-slide for metropolis ([#349](https://github.com/touying-typ/touying/pull/349)) +- feat: add warning for empty slide content height detection + +### Documentation + +- docs: add multiple columns example and improve docs structure + +## v0.7.1 + +### Features + +- feat(agents): `breakable` and `clip` options to avoid slide overflow ([#336](https://github.com/touying-typ/touying/pull/336)) +- feat(components): add `lazy-v` (`lazy-h`) and `lazy-layout` for equalizing multi-column (-row) block heights (widths) ([#339](https://github.com/touying-typ/touying/pull/339)) +- feat: additional `contact` and `extra` field in `config-info` ([#342](https://github.com/touying-typ/touying/pull/342)) +- feat: `touying-get-config` function ([#333](https://github.com/touying-typ/touying/pull/333)) + +### Fixes + +- fix: fix `fit-to-height` and `size-to-pt` and allow text reflow ([#332](https://github.com/touying-typ/touying/pull/332)) +- fix: fix waypoint markers ([#341](https://github.com/touying-typ/touying/pull/341)) + + +## v0.7.0 + +### Features + +- **major feature:** a named waypoint feature ([#298](https://github.com/touying-typ/touying/pull/298)) +- feat(waypoint): start param and Waypoints in handout-subslides ([#304](https://github.com/touying-typ/touying/pull/304)) +- feat: auto, "h"-here string and inverse function for string subslide-numbers and waypoints ([#301](https://github.com/touying-typ/touying/pull/301)) +- feat: implicitly allow fn-wrapper based animation functions via reducer ([#300](https://github.com/touying-typ/touying/pull/300)) + +### Fixes + +- fix: fix cover-with-rect breaking long lines of text when partially hidden and fallback functions for color/alpha cover ([#328](https://github.com/touying-typ/touying/pull/328)) +- fix: using explicit numbering in display-current-heading when style=auto ([#329](https://github.com/touying-typ/touying/pull/329)) +- fix: fix ghost slides with show rules. Fix proper consistent handling of show rules and defer keyword ([#317](https://github.com/touying-typ/touying/pull/317)) +- fix: alert not delayed ([#316](https://github.com/touying-typ/touying/pull/316)) +- fix: remove redundant nested text call ([#324](https://github.com/touying-typ/touying/pull/324)) +- fix: function alternatives-match takes into account parameter stretch ([#320](https://github.com/touying-typ/touying/pull/320)) +- fix: correctly handle page margin merge/precedence ([#322](https://github.com/touying-typ/touying/pull/322)) +- fix: fix cover spacing issues surrounding lists ([#303](https://github.com/touying-typ/touying/pull/303)) +- fix: correctly parses negative subslide indices (ints, arrays) for handout-subslides ([#307](https://github.com/touying-typ/touying/pull/307)) +- fix: slide function does not update via scoped import ([#310](https://github.com/touying-typ/touying/pull/310)) + +Thanks for the contributions from [@zral0kh](https://github.com/zral0kh), [@Andrew15-5](https://github.com/Andrew15-5), [@navdeeprana](https://github.com/navdeeprana), and [@Cemoixerestre](https://github.com/Cemoixerestre). + +## v0.6.3 + +A major bugfix release, fixing many long-standing bugs and introducing many practical features. + +### Features + +- **feat: add `#jump(n, relative: bool)` as unified animation control; redefine `#pause`/`#meanwhile` as sugar** +- feat: add `#handout-only` for inline content and `` label for handout-exclusive slides ([#286](https://github.com/touying-typ/touying/pull/286)) +- feat: add `handout-subslides` to control which subslides appear in handout mode ([#288](https://github.com/touying-typ/touying/pull/288)) +- feat: add `#touying-raw` for animated code block reveals ([#283](https://github.com/touying-typ/touying/pull/283)) +- feat: add full-screen speaker notes mode with slide thumbnail (`show-only-notes`) ([#281](https://github.com/touying-typ/touying/pull/281)) +- feat: support arbitrary aspect ratios (e.g. 16-10) across all themes and speaker-note second screen ([#280](https://github.com/touying-typ/touying/pull/280)) +- feat: add `#item-by-item` animation for list, enum, and terms ([#278](https://github.com/touying-typ/touying/pull/278)) +- feat(recall): add subslide parameter to `#touying-recall` ([#285](https://github.com/touying-typ/touying/pull/285)) +- feat: add `default-composer` to config-common for global slide layout configuration ([#284](https://github.com/touying-typ/touying/pull/284)) +- feat: add `cover-fn` parameter to `uncover` for external package integration (e.g. Fletcher) ([#267](https://github.com/touying-typ/touying/pull/267)) +- feat: minislides can be displayed inline ([#228](https://github.com/touying-typ/touying/pull/228)) +- theme: improve appearance of long author lists in university and stargazer theme ([#242](https://github.com/touying-typ/touying/pull/242)) +- theme(simple): make simple-theme respect color configuration for deco-format ([#252](https://github.com/touying-typ/touying/pull/252)) +- theme(aqua,stargazer): add extra parameter to title-slide ([#291](https://github.com/touying-typ/touying/pull/291)) + +### Fixes + +- fix: prevent ghost-slide blank pages from `touying-set-config` anchor regression ([#289](https://github.com/touying-typ/touying/pull/289)) +- fix: styled content on first slide no longer creates extra slides ([#287](https://github.com/touying-typ/touying/pull/287)) +- fix: remove unoutlined headings from navigation +- fix: fix `#meanwhile` being ignored inside grid cells, boxes, and other containers ([#274](https://github.com/touying-typ/touying/pull/274)) +- fix: fix `config: parameter` silently ignored across all themes ([#273](https://github.com/touying-typ/touying/pull/273)) +- fix: fix slides after `#show`/`#set` rules not rendering subsequent slides ([#268](https://github.com/touying-typ/touying/pull/268)) +- fix: fix title page PDF page label causing pdfpc presenter notes mismatch ([#277](https://github.com/touying-typ/touying/pull/277)) +- fix: fix duplicate label error for labeled footnotes with `#pause` animations ([#275](https://github.com/touying-typ/touying/pull/275)) +- fix: fix `#pause` inside `#speaker-note` body (nested list items) ([#282](https://github.com/touying-typ/touying/pull/282)) +- theme(dewdrop): fix body content under level-1 heading was silently dropped ([#279](https://github.com/touying-typ/touying/pull/279)) +- theme(stargazer): update stargazer theme margins and fix [#259](https://github.com/touying-typ/touying/pull/259) + +### Documentation + +- **docs(BIG CHANGE): refactor docs website and add references page** +- docs: reduce README noise, improve first impression ([#297](https://github.com/touying-typ/touying/pull/297)) +- docs: restructure docs + add docs-preview CI for PRs ([#296](https://github.com/touying-typ/touying/pull/296)) +- docs: comprehensive docstring improvements across all source files ([#294](https://github.com/touying-typ/touying/pull/294)) + +### Miscellaneous + +- chore: add `copilot-setup-steps.yml` and improve `copilot-instructions.md` ([#292](https://github.com/touying-typ/touying/pull/292)) + +### Theme Migration Guide + +**For theme developers upgrading to v0.6.3:** + +1. **Move `config` to the last position in `utils.merge-dicts`** to allow user overrides: + ```typst + // Before + self = utils.merge-dicts(self, config, config-page(...)) + + // After + self = utils.merge-dicts(self, config-page(...), config) + ``` + +2. **Replace `paper` with `utils.page-args-from-aspect-ratio`** to support arbitrary aspect ratios: + ```typst + // Before + config-page(paper: "presentation-" + aspect-ratio, ...) + + // After + config-page(..utils.page-args-from-aspect-ratio(aspect-ratio), ...) + ``` + +## v0.6.2 + +### Features + +- feat: allow customisation of `components.checkerboard` ([#161](https://github.com/touying-typ/touying/pull/161)) + +### Fixes + +- fix: support ratio and relative margins for full-width headers ([#256](https://github.com/touying-typ/touying/pull/256)) +- fix: fix `magic.bibliography-as-footnote` in Typst 0.14 ([#249](https://github.com/touying-typ/touying/pull/249)) +- fix: theorion package is broken with Typst 0.14.0 ([#237](https://github.com/touying-typ/touying/pull/237)) +- fix: update `components.typ` and pass named arguments to grid ([#207](https://github.com/touying-typ/touying/pull/207)) +- fix: fix `#meanwhile` in cetz ([#205](https://github.com/touying-typ/touying/pull/205)) +- fix: documentation contains unclosed raw text error ([#187](https://github.com/touying-typ/touying/pull/187)) +- fix: use correct circle symbol ([#171](https://github.com/touying-typ/touying/pull/171)) +- fix: use regex to override colors of equations ([#167](https://github.com/touying-typ/touying/pull/167)) +- fix: `show-hide-set-list-marker-none` with full enum ([#157](https://github.com/touying-typ/touying/pull/157)) +- fix: remove dump and label-it function for better cache + +### Miscellaneous + +- docs: update README, bump versions of deps, and fix comment docs +- ci: add more tests, bump versions of `tytanic`, and update typstyle workflow ([#221](https://github.com/touying-typ/touying/pull/221), [#261](https://github.com/touying-typ/touying/pull/261)) + + +## v0.6.1 + +Added support for the [theorion](https://github.com/OrangeX4/typst-theorion) package, and used it as the default math theorem environment. + +## v0.6.0 + +It's not a big update, but it's the first touying release since typst 0.13 was released. + +### Features + +- feat: add auto style for display-current-heading. + - For users, you can use `show heading: set text(blue)` to change color for heading in some themes like `dewdrop`. + - For theme creator, you can use syntax like `utils.display-current-heading(level: 1, style: auto)` to achieve the same result. +- feat: apply config-info information to `set document`. +- feat: set `stretch: false` by default for `alternatives` functions. This is **a minor breaking change**, but I think it would be more intuitive: no auto empty space. + +### Fixes + +- fix: fix error with uncover using semi-transparent-cover +- fix: fix type string comparison https://github.com/touying-typ/touying/pull/153 +- fix: fix horizontal-line bug in typst 0.13.0 +- refactor: fix display-current-short-heading + + +## v0.5.4 & v0.5.5 + +### Features + +- docs: improve param documentation and we have better hints for tinymist https://github.com/touying-typ/touying/pull/98 +- feat: fake frozon states support for `heading` https://github.com/touying-typ/touying/pull/124 +- feat: add alpha-changing-cover and color-changing-cover https://github.com/touying-typ/touying/pull/129 +- feat: add effect function https://github.com/touying-typ/touying/issues/111 + - Example: `#effect(text.with(fill: red), "2-")[Something]` will display `[Something]` if the current slide is 2 or later. +- feat: add argument `config: (..)` for `xxx-slide` functions +- feat: add `align` argument for university theme + +### Fixes + +- fix: also hide enum numbers with show-hide-set-list-marker-none https://github.com/touying-typ/touying/pull/114 +- fix: fixed progress bar not to break apart when global figure gutter is set nonzero https://github.com/touying-typ/touying/pull/120 +- fix: fixed frozen-counters bug with multiple #pause commands https://github.com/touying-typ/touying/pull/124 +- fix: fixed incorrect page num when draft is true https://github.com/touying-typ/touying/pull/125 +- fix: fix behaviors of fit-to-height and fit-to-width partially https://github.com/touying-typ/touying/pull/131 +- fix: duplicated footnotes in headings https://github.com/touying-typ/touying/pull/132 +- fix: do not hardcode page sizes https://github.com/touying-typ/touying/pull/134 +- fix: add default numbering for page https://github.com/touying-typ/touying/issues/100 +- refactor: move show-strong-with-alert to per-slide level https://github.com/touying-typ/touying/issues/123 +- refactor: remove unnecessary `config-page(fill: ...)` +- theme(metropolis): fix color of title page and fix https://github.com/touying-typ/touying/issues/103 +- theme(metropolis): fixed metropolis slide's header to return content if title is specified https://github.com/touying-typ/touying/pull/126 +- theme(metropolis): respect colors dict in metropolis theme https://github.com/touying-typ/touying/pull/133 +- fix: fix bug of `#effect` function + +Thanks for the contributions from [@enklht](https://github.com/enklht). + + +## v0.5.3 + +### Features + +- feat: add `stretch` parameter for `#alternatives[]` function class. This allows us to handle cases where the internal element is a context expression. +- feat: add `config-common(align-enum-marker-with-baseline: true)` for aligning the enum marker with the baseline. +- feat: add `linebreaks` option to `components.mini-slides`. https://github.com/touying-typ/touying/pull/96 +- feat: add `` label to skip a new-section-slide. +- feat: add `config-common(show-hide-set-list-marker-none: true)` to make the markers of `list` and `enum` invisible after `#pause`. +- feat: add `config-common(bibliography-as-footnote: bibliography(title: none, "ref.bib"))` to display the bibliography in footnotes. +- refactor: add `config-common(show-strong-with-alert: true)` configuration to display strong text with an alert. (small breaking change for some themes) +- refactor: refactor `display-current-heading` for preserving heading style in title and subtitle. https://github.com/touying-typ/touying/issues/71 +- refactor: make `new-section-slide-fn` function class can receive `body` parameter. We can use `receive-body-for-new-section-slide-fn` to control it. **(Breaking change)** + - For example, you can add `#speaker-note[]` for a new section slide, like `= Section Title \ #speaker-note[]`. + - If you don't want to append content to the body of the new section slide, you can use `---` after the section title. + +### Fixes + +- fix outdated documentation. +- fix bug of `enable-frozen-states-and-counters` in handout mode. +- fix unusable `square()` function. https://github.com/touying-typ/touying/issues/73 +- fix hidden footer for `show-notes-on-second-screen: bottom`. https://github.com/touying-typ/touying/issues/89 +- fix metadata element in table cells. https://github.com/touying-typ/touying/issues/77 https://github.com/touying-typ/touying/issues/95 +- fix `auto-offset-for-heading` to `false` by default. +- fix uncover/only hides more content than it should. https://github.com/touying-typ/touying/issues/85 +- theme(simple): fix wrong title and subtitle. https://github.com/touying-typ/touying/issues/70 + + +## v0.5.1 & v0.5.2 + +- Fix somg bugs. + + +## v0.5.0 + +This is a significant disruptive version update. Touying has removed many mistakes that resulted from incorrect decisions. We have redesigned numerous features. The goal of this version is to make Touying more user-friendly, more flexible, and more powerful. + +**Major changes include:** + +- Avoiding closures and OOP syntax, which makes Touying's configuration simpler and allows for the use of document comments to provide more auto-completion information for the slide function. + - The existing `#let slide(self: none, ..args) = { .. }` is now `#let slide(..args) = touying-slide-wrapper(self => { .. })`, where `self` is automatically injected. + - We can use `config-xxx` syntax to configure Touying, for example, `#show: university-theme.with(aspect-ratio: "16-9", config-colors(primary: blue))`. +- The `touying-slide` function no longer includes parameters like `section`, `subsection`, and `title`. These will be automatically inserted into the slide as invisible level 1, 2, or 3 headings via `self.headings` (controlled by the `slide-level` configuration). + - We can leverage the powerful headings provided by Typst to support numbering, outlines, and bookmarks. + - Headings within the `#slide[= XXX]` function will be adjusted to level `slide-level + 1` using the `offset` parameter. + - We can use labels on headings to control many aspects, such as supporting the `` and other special labels, implementing short headings, or recalling a slide with `#touying-recall()`. +- Touying now supports the normal use of `set` and `show` rules at any position, without requiring them to be in specific locations. + +A simple usage example is shown below, and more examples can be found in the `examples` directory: + +```typst +#import "@preview/touying:0.5.0": * +#import themes.university: * + +#show: university-theme.with( + aspect-ratio: "16-9", + config-info( + title: [Title], + subtitle: [Subtitle], + author: [Authors], + date: datetime.today(), + institution: [Institution], + logo: emoji.school, + ), +) + +#set heading(numbering: "1.1") + +#title-slide() + += The Section + +== Slide Title + +#lorem(40) +``` + +**Theme Migration Guide:** + +For detailed changes to specific themes, you can refer to the `themes` directory. Generally, if you want to migrate an existing theme, you should: + +1. Rename the `register` function to `xxx-theme` and remove the `self` parameter. +2. Add a `show: touying-slides.with(..)` configuration. + - Change `self.methods.colors` to `config-colors(primary: rgb("#xxxxxx"))`. + - Change `self.page-args` to `config-page()`. + - Change `self.methods.slide = slide` to `config-methods(slide: slide)`. + - Change `self.methods.new-section-slide = new-section-slide` to `config-methods(new-section-slide: new-section-slide)`. + - Change private theme variables like `self.xxx-footer` to `config-store(footer: [..])`, which you can access through `self.store.footer`. + - Move the configuration of headers and footers into the `slide` function rather than in the `xxx-theme` function. + - You can directly use `set` or `show` rules in `xxx-theme` or configure them through `config-methods(init: (self: none, body) => { .. })` to fully utilize the `self` parameter. +3. For `states.current-section-with-numbering`, you can use `utils.display-current-heading(level: 1)` instead. + - If you only need the previous heading regardless of whether it is a section or a subsection, use `self => utils.display-current-heading(depth: self.slide-level)`. +4. The `alert` function can be replaced with `config-methods(alert: utils.alert-with-primary-color)`. +5. The `touying-outline()` function is no longer needed; you can use `components.adaptive-columns(outline())` instead. Consider using `components.progressive-outline()` or `components.custom-progressive-outline()`. +6. Replace `states.slide-counter.display() + " / " + states.last-slide-number` with `context utils.slide-counter.display() + " / " + utils.last-slide-number`. That is, we no longer use `states` but `utils`. +7. Remove the `slides` function; we no longer need this function. Instead of implicitly injecting `title-slide()`, explicitly use `#title-slide()`. If necessary, consider adding it in the `xxx-theme` function. +8. Change `#let slide(self: none, ..args) = { .. }` to `#let slide(..args) = touying-slide-wrapper(self => { .. })`, where `self` is automatically injected. + - Change specific parameter configurations to `self = utils.merge-dicts(self, config-page(fill: self.colors.neutral-lightest))`. + - Remove `self = utils.empty-page(self)` and use `config-common(freeze-slide-counter: true)` and `config-page(margin: 0em)` instead. + - Change `(self.methods.touying-slide)()` to `touying-slide()`. +9. You can insert visible headings into slides by configuring `config-common(subslide-preamble: self => text(1.2em, weight: "bold", utils.display-current-heading(depth: self.slide-level)))`. +10. Finally, don't forget to add document comments to your functions so your users can get better auto-completion hints, especially when using the Tinymist plugin. + +**Other Changes:** + +- theme(stargazer): new stargazer theme modified from [Coekjan/touying-buaa](https://github.com/Coekjan/touying-buaa). +- feat: implemented fake frozen states support, allowing you to use numbering and `#pause` normally. This behavior can be controlled with `enable-frozen-states-and-counters`, `frozen-states`, and `frozen-counters` in `config-common()`. +- feat: implemented `label-only-on-last-subslide` functionality to prevent non-unique label warnings when working with `@equation` and `@figure` in conjunction with `#pause` animations. +- feat: added the `touying-recall(