-
Notifications
You must be signed in to change notification settings - Fork 0
Prototype single files for web and slides #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
0960695
d533125
7c067cb
351eebc
9be5f61
7b35507
ea56c96
ad10642
fd0ca78
5b275e0
d49c49c
184d313
24311eb
ad8b8ef
d10e77a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,4 +9,10 @@ _site | |
| _freeze | ||
| .DS_Store | ||
|
|
||
| *_files/ | ||
| *.html | ||
|
|
||
| **/*.quarto_ipynb | ||
|
|
||
| /.luarc.json | ||
| web_and_slides_autogenerated.lua | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,3 +1,190 @@ | ||||||||||||||||||||||||||||||||||
| List of modules built by the Palaeoverse team. | ||||||||||||||||||||||||||||||||||
| # Palaeoverse Modules | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| One folder per module. | ||||||||||||||||||||||||||||||||||
| List of teaching modules built by the Palaeoverse team. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| One folder per module: `<module>/index.qmd`, plus whatever images and data it | ||||||||||||||||||||||||||||||||||
| needs. Every module is rendered twice from that single source: 1) as a page on the | ||||||||||||||||||||||||||||||||||
| [Palaeoverse website](https://palaeoverse.org/training/modules) and 2) as a | ||||||||||||||||||||||||||||||||||
| reveal.js slide deck (`index-slides.html`) for teaching the same material live. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| The two files at the root of this repo exist to make one source serve both | ||||||||||||||||||||||||||||||||||
| outputs: | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| | File | Role | | ||||||||||||||||||||||||||||||||||
| | --- | --- | | ||||||||||||||||||||||||||||||||||
| | `web_and_slides.lua` | Pandoc/Quarto filter, applied at render time. Decides what appears on the website, what appears on the slides, and how the slides are broken up. | | ||||||||||||||||||||||||||||||||||
| | `web_and_slides.r` | One-shot authoring helper. Converts a finished long-form document into the tagged form the filter expects. | | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Authoring a module | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ## Front matter | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Start from an existing module (`ggplot/index.qmd` is a good template). These | ||||||||||||||||||||||||||||||||||
| fields matter: | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ```yaml | ||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||
| title: "Plotting in R with ggplot2" | ||||||||||||||||||||||||||||||||||
| description: "Visualizing your data with the grammar of graphics" | ||||||||||||||||||||||||||||||||||
| author: "Will Gearty" | ||||||||||||||||||||||||||||||||||
| date: "2026-06-12" | ||||||||||||||||||||||||||||||||||
| categories: [r, tidyverse, dataviz] # various tags | ||||||||||||||||||||||||||||||||||
| difficulty: Beginner # Beginner/Intermediate/Advanced | ||||||||||||||||||||||||||||||||||
| image: images/2d_density.png # thumbnail for module | ||||||||||||||||||||||||||||||||||
| format: | ||||||||||||||||||||||||||||||||||
| html: default | ||||||||||||||||||||||||||||||||||
| revealjs: | ||||||||||||||||||||||||||||||||||
| smaller: true | ||||||||||||||||||||||||||||||||||
| output-file: index-slides.html # the deck, alongside the page | ||||||||||||||||||||||||||||||||||
| execute: | ||||||||||||||||||||||||||||||||||
| output-location: fragment # slide output reveals on click | ||||||||||||||||||||||||||||||||||
| echo: true | ||||||||||||||||||||||||||||||||||
| freeze: auto # must be auto, not true | ||||||||||||||||||||||||||||||||||
| filters: | ||||||||||||||||||||||||||||||||||
| - at: pre-ast | ||||||||||||||||||||||||||||||||||
| path: web_and_slides_autogenerated.lua | ||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| `difficulty`, `categories` and `freeze: auto` are enforced by CI (see | ||||||||||||||||||||||||||||||||||
| [Technical summary](#technical-summary)). The `filters` entry is what activates | ||||||||||||||||||||||||||||||||||
| everything below; `web_and_slides.r` adds it for you, or you can copy it. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ## Writing for two outputs | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Three fenced-div (`:::`) classes control where content lands: | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| | Class | Website Tutorial | Slides | | ||||||||||||||||||||||||||||||||||
| | --- | --- | --- | | ||||||||||||||||||||||||||||||||||
| | `.narration` | normal prose | speaker notes | | ||||||||||||||||||||||||||||||||||
| | `.slides-only` | dropped | shown on the slide | | ||||||||||||||||||||||||||||||||||
| | `.html-only` | shown | dropped | | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Anything not wrapped in one of these appears in both outputs. So the usual shape | ||||||||||||||||||||||||||||||||||
| of a module is: headings and code chunks shared by both outputs, the connecting | ||||||||||||||||||||||||||||||||||
| prose in `.narration` (a paragraph on the page, a note you talk from on the | ||||||||||||||||||||||||||||||||||
| slide), and the occasional `.slides-only` bullet summary or `.html-only` aside. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ````markdown | ||||||||||||||||||||||||||||||||||
| ## Making a scatter plot | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ::: {.narration} | ||||||||||||||||||||||||||||||||||
| On the website this is a paragraph of explanation. On the slides it is what you | ||||||||||||||||||||||||||||||||||
| say out loud while the plot is up. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Consecutive paragraphs can share one block. | ||||||||||||||||||||||||||||||||||
| ::: | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ::: {.slides-only} | ||||||||||||||||||||||||||||||||||
| - x is body mass | ||||||||||||||||||||||||||||||||||
| - y is flipper length | ||||||||||||||||||||||||||||||||||
| ::: | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ```{r} | ||||||||||||||||||||||||||||||||||
| ggplot(penguins) + | ||||||||||||||||||||||||||||||||||
| aes(x = body_mass, y = flipper_len) + | ||||||||||||||||||||||||||||||||||
| geom_point() | ||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||
| ```` | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ## Automated slide rendering via `web_and_slides.lua` | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| The following changes are applied to the reveal.js slides via our custom Lua filter: | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - **Headings become slides:** `##` starts a slide as usual; `###` and deeper are | ||||||||||||||||||||||||||||||||||
| promoted so each also gets its own slide, instead of piling onto the parent. | ||||||||||||||||||||||||||||||||||
| A `#` heading becomes a centered divider slide, so don't put content under one. | ||||||||||||||||||||||||||||||||||
| - **One plot per slide:** The slide closes after each figure. Prose that follows | ||||||||||||||||||||||||||||||||||
| a figure moves to the next slide (introducing it), unless nothing but prose | ||||||||||||||||||||||||||||||||||
| remains before the next heading — then it stays put rather than making a blank | ||||||||||||||||||||||||||||||||||
| slide. Split slides repeat the current heading, so they keep a title. | ||||||||||||||||||||||||||||||||||
| - **Callouts get their own slide:** A callout is un-boxed onto a slide of its | ||||||||||||||||||||||||||||||||||
| own, titled by its own heading. Give a callout a `## Heading` as its first line | ||||||||||||||||||||||||||||||||||
| (rather than `title="..."`) if you want that title on the slide; an untitled | ||||||||||||||||||||||||||||||||||
| callout keeps the section title. | ||||||||||||||||||||||||||||||||||
| - **Multi-chunk slides build up:** A slide holding two or more code chunks is | ||||||||||||||||||||||||||||||||||
| expanded into an auto-animate sequence: one step per chunk, earlier chunks | ||||||||||||||||||||||||||||||||||
| staying on screen, and the notes for each chunk advancing with it. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Preview both outputs with: | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ```sh | ||||||||||||||||||||||||||||||||||
| quarto render ggplot/index.qmd # -> index.html and index-slides.html | ||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ## `web_and_slides.r` Helper | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| The `web_and_slides.r` helper file takes a long-form document and mechanically prepares it: | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ```sh | ||||||||||||||||||||||||||||||||||
| Rscript web_and_slides.r <input.qmd> [output.qmd] | ||||||||||||||||||||||||||||||||||
| [--filter=<path/to/filter.lua>] [--no-inject] [--no-settings] | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+120
to
+121
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are there cases where we need to provide the filter and other arguments? Could this be simplified to: Rscript web_and_slides.r <input.qmd> <output.qmd>Also, this needs to run in the terminal and everyone is not familiar with that, is there a way to run it with
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was developed as a CLI tool, |
||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| It does the following: | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| 1. Wraps each set of consecutive prose paragraphs in a single | ||||||||||||||||||||||||||||||||||
| `::: {.narration}` block. Headings, code chunks, lists, blockquotes, | ||||||||||||||||||||||||||||||||||
| tables, standalone images, and existing fenced divs (including callouts and | ||||||||||||||||||||||||||||||||||
| everything inside them) are left untouched. | ||||||||||||||||||||||||||||||||||
| 2. Registers the filter in the front matter at the `pre-ast` stage, replacing any | ||||||||||||||||||||||||||||||||||
| earlier registration. `--no-inject` skips this; `--filter=` names a different | ||||||||||||||||||||||||||||||||||
| file. | ||||||||||||||||||||||||||||||||||
| 3. Sets slide-friendly YAML (skip with `--no-settings`): | ||||||||||||||||||||||||||||||||||
| - adds `execute.echo: true` (renders source code on slides) | ||||||||||||||||||||||||||||||||||
| - adds `execute.output-location: fragment` (renders code results as separate chunk) | ||||||||||||||||||||||||||||||||||
| - adds `format.revealjs.smaller: true` (text shrinks to fit on slides) | ||||||||||||||||||||||||||||||||||
| - removes `format.revealjs.scrollable` (disables scrolling through slides) | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+130
to
+137
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was trying to make the whole procedure as painless as possible for users (by doing the YAML changes for them). I'm fine with removing the |
||||||||||||||||||||||||||||||||||
| 4. Reports headings that will render awkwardly (e.g., `#` become centered title slides). | ||||||||||||||||||||||||||||||||||
| You should fix these by hand. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| The front matter is checked for valid YAML before anything is written. Needs the | ||||||||||||||||||||||||||||||||||
| `readr`, `stringr`, `yaml`, and `fs` packages. | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+141
to
+142
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's only in CI, right? Does this need to be mentioned here?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These checks are also done with the web_and_slides.r script: Lines 216 to 231 in d10e77a
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| With no `output.qmd` specified it rewrites the input in place. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Two ways to build a module | ||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should come before explaining the lua + R script workflow above since this workflow is only relevant for the "long-form first then convert" section. |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ## 1. Long-form first, then convert | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| _Best when the module is primarily a written tutorial, or already exists as prose._ | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Write the module as an ordinary prose-and-code document, ignoring slides | ||||||||||||||||||||||||||||||||||
| entirely. When it reads well, run `web_and_slides.r` over it once, then clean up | ||||||||||||||||||||||||||||||||||
| the result by hand: act on any headings it flagged and add `:::{.slides-only}` / | ||||||||||||||||||||||||||||||||||
| `:::{.html-only}` blocks where the two outputs should diverge. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ```sh | ||||||||||||||||||||||||||||||||||
| # write the preliminary tutorial in mymodule/index.qmd.orig | ||||||||||||||||||||||||||||||||||
| Rscript web_and_slides.r mymodule/index.qmd.orig mymodule/index.qmd | ||||||||||||||||||||||||||||||||||
| quarto render mymodule/index.qmd | ||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| The script is intended to be run as a **single pass once the long-form version is | ||||||||||||||||||||||||||||||||||
| finished**. However, in principle it can be run on the same file multiple times. | ||||||||||||||||||||||||||||||||||
| Prose already inside a `.narration` block is left alone, so a second run over its | ||||||||||||||||||||||||||||||||||
| own output changes nothing. If you start hand-editing the converted file, keep | ||||||||||||||||||||||||||||||||||
| editing that file. If you would rather keep iterating on the long-form text, | ||||||||||||||||||||||||||||||||||
| keep it alongside as `index.qmd.orig` and regenerate `index.qmd` (but any hand | ||||||||||||||||||||||||||||||||||
| cleanup you did to `index.qmd` will need redoing). | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| ## 2. Tag as you go | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| _Best when you are thinking about the slides and the prose tutorial at the same | ||||||||||||||||||||||||||||||||||
| time, and when you want fine control over which output gets what._ | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Skip `web_and_slides.r` completely. Write `index.qmd` with the intent to render | ||||||||||||||||||||||||||||||||||
| both output types from the beginning. Copy the `filters` entry and the | ||||||||||||||||||||||||||||||||||
| slide-friendly `execute` / `revealjs` settings from another module's front matter. | ||||||||||||||||||||||||||||||||||
| Then, as you write use an `.html-only` block if you only want the text to | ||||||||||||||||||||||||||||||||||
| appear in the prose tutorial, a `.slides-only` block if a section should only | ||||||||||||||||||||||||||||||||||
| appear on the slides (e.g., bullet points), or a `.narration` block have | ||||||||||||||||||||||||||||||||||
| content appear in the prose tutorial and be shown as speaker notes for the slides. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Additional references: | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| - Quarto tutorial ([with Positron](https://quarto.org/docs/get-started/hello/positron.html) | [with RStudio](https://quarto.org/docs/get-started/computations/rstudio.html)) | ||||||||||||||||||||||||||||||||||
| - [Markdown basics in Quarto](https://quarto.org/docs/authoring/markdown-basics.html) | ||||||||||||||||||||||||||||||||||
| - [HTML basics in Quarto](https://quarto.org/docs/output-formats/html-basics.html) | ||||||||||||||||||||||||||||||||||
| - [Revealjs in Quarto](https://quarto.org/docs/presentations/revealjs/) | ||||||||||||||||||||||||||||||||||
| - [Quarto Listings](https://quarto.org/docs/websites/website-listings.html) | ||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| project: | ||
| type: default | ||
| # modules only, so README.md / LICENSE.md aren't rendered | ||
| render: | ||
| - "*/*.qmd" | ||
| # refresh each module's copy of the Lua filter before rendering | ||
| pre-render: sync_filter.r |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we had chatted on Zulip about allowing both having a single qmd that creates the long format and the slides, and two qmds with one per format? I think @LewisAJones would prefer two qmds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally would prefer we stick to a single document to reduce maintenance overhead (since I have a hunch that the individual authors will not be maintaining their own modules longterm), but I suppose as long as everything is reproducible (and easy to maintain), it wouldn't be the end of the world if someone makes two separate documents (but I would prefer that we avoid using powerpoints, etc).