From b5c5ff95f0fb308a8bf6f44e3bd456db9f5b54a6 Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Wed, 11 Feb 2026 10:56:13 +0100 Subject: [PATCH 1/4] Adds composite setup action for CI workflows --- .github/workflows/setup/action.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/workflows/setup/action.yml diff --git a/.github/workflows/setup/action.yml b/.github/workflows/setup/action.yml new file mode 100644 index 0000000..36ba1ae --- /dev/null +++ b/.github/workflows/setup/action.yml @@ -0,0 +1,10 @@ +name: Setup Rust +description: Setup Rust toolchain + +runs: + using: composite + steps: + - name: Setup Rust toolchain + uses: dtolnay/rust-toolchain@stable + - name: Cache cargo dependencies + uses: Swatinem/rust-cache@v2 From 8049eb37360655cfa0570c74301f1543460a651b Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Wed, 11 Feb 2026 11:06:17 +0100 Subject: [PATCH 2/4] Fixes pre-release CI for submodules and cargo publish Updates tests --- .github/workflows/pre-release.yml | 2 + examples/init_template/rheo.toml | 11 ++ src/css/style.css | 117 ------------------ src/rs/init.rs | 12 +- src/rs/output.rs | 2 +- .../templates/init}/content/about.typ | 0 .../templates/init}/content/img/header.svg | 0 .../templates/init}/content/index.typ | 0 .../templates/init}/content/references.bib | 0 src/templates/init/rheo.toml | 11 ++ .../templates/init}/style.css | 0 tests/harness.rs | 68 +++++++++- tests/helpers/comparison.rs | 7 +- tests/helpers/reference.rs | 4 +- .../cases/pdf_merge/html/style.metadata.json | 2 +- .../blog_post/html/style.metadata.json | 6 +- .../blog_site/html/style.metadata.json | 6 +- .../html/style.metadata.json | 6 +- .../html/style.metadata.json | 6 +- .../html/style.metadata.json | 6 +- .../fcl_site/html/style.metadata.json | 2 +- .../epub/init_template.metadata.json | 11 -- .../init_template/epub/xhtml/about.xhtml | 12 -- .../init_template/epub/xhtml/index.xhtml | 18 --- .../examples/init_template/html/about.html | 15 --- .../examples/init_template/html/index.html | 21 ---- .../init_template/html/style.metadata.json | 6 - .../pdf/init_template.metadata.json | 5 - .../html/style.metadata.json | 6 +- .../html/style.metadata.json | 6 +- .../html/style.metadata.json | 6 +- .../pdf_merge_false/html/style.metadata.json | 6 +- .../html/style.metadata.json | 6 +- .../rheo_docs/epub/rheo_docs.metadata.json | 2 +- .../rheo_docs/epub/xhtml/custom-css.xhtml | 4 +- .../examples/rheo_docs/html/custom-css.html | 4 +- .../rheo_docs/html/style.metadata.json | 2 +- .../rheo_docs/pdf/rheo_docs.metadata.json | 2 +- .../target_function/html/style.metadata.json | 6 +- .../html/style.metadata.json | 6 +- .../html/style.metadata.json | 6 +- .../portable_epubs/html/style.metadata.json | 6 +- .../index/html/style.metadata.json | 6 +- .../severance-ep-1/html/style.metadata.json | 6 +- .../html/style.metadata.json | 6 +- 45 files changed, 166 insertions(+), 276 deletions(-) delete mode 100644 src/css/style.css rename {examples/init_template => src/templates/init}/content/about.typ (100%) rename {examples/init_template => src/templates/init}/content/img/header.svg (100%) rename {examples/init_template => src/templates/init}/content/index.typ (100%) rename {examples/init_template => src/templates/init}/content/references.bib (100%) create mode 100644 src/templates/init/rheo.toml rename {examples/init_template => src/templates/init}/style.css (100%) delete mode 100644 tests/ref/examples/init_template/epub/init_template.metadata.json delete mode 100644 tests/ref/examples/init_template/epub/xhtml/about.xhtml delete mode 100644 tests/ref/examples/init_template/epub/xhtml/index.xhtml delete mode 100644 tests/ref/examples/init_template/html/about.html delete mode 100644 tests/ref/examples/init_template/html/index.html delete mode 100644 tests/ref/examples/init_template/html/style.metadata.json delete mode 100644 tests/ref/examples/init_template/pdf/init_template.metadata.json diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index cda996e..9730d80 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -42,6 +42,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + submodules: recursive - name: Add target run: rustup target add ${{ matrix.target }} - name: Setup diff --git a/examples/init_template/rheo.toml b/examples/init_template/rheo.toml index a213c61..0f513cc 100644 --- a/examples/init_template/rheo.toml +++ b/examples/init_template/rheo.toml @@ -9,3 +9,14 @@ merge = true [epub.spine] title = "rheo_project" vertebrae = ["index.typ", "about.typ"] +version = "0.1.2" +content_dir = "content" + +[pdf.spine] +title = "rheo_project" +vertebrae = ["index.typ"] +merge = true + +[epub.spine] +title = "rheo_project" +vertebrae = ["index.typ", "about.typ"] diff --git a/src/css/style.css b/src/css/style.css deleted file mode 100644 index 235fc05..0000000 --- a/src/css/style.css +++ /dev/null @@ -1,117 +0,0 @@ -/* ============================================ - CSS Variables - ============================================ */ -:root { - --background-color: #fdfdfd; - --text-color: #1a1a1a; - --link-color: #1a1a1a; - --blockquote-border: #e6e6e6; - --blockquote-text: #606060; -} - -/* ============================================ - Base Layout - ============================================ */ -body { - background-color: var(--background-color); - color: var(--text-color); - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; - font-size: 1em; - line-height: 1.3; - margin: 0 auto; - padding: 50px; - max-width: 36em; -} - -/* ============================================ - Typography - ============================================ */ -h1, h2, h3, h4, h5, h6 { - color: var(--text-color); - font-weight: normal; - margin-top: 1.5em; - margin-bottom: 0.5em; -} - -/* ============================================ - Links - ============================================ */ -a { - color: var(--link-color); - text-decoration: underline; -} - -a:hover { - opacity: 0.7; -} - -/* ============================================ - Lists - ============================================ */ -ul, ol { - padding-left: 2em; - margin: 1em 0; -} - -li {} - -/* ============================================ - Media - ============================================ */ -img, video { - max-width: 100%; - height: auto; - display: block; - margin: 1.5em 0; -} - -/* ============================================ - Code - ============================================ */ -code { - font-family: 'Courier New', monospace; - background-color: #f5f5f5; - padding: 0.2em 0.4em; - border-radius: 3px; - font-size: 0.9em; -} - -/* ============================================ - Blockquotes - ============================================ */ -blockquote { - margin: 1.5em 0; - padding-left: 1em; - border-left: 2px solid var(--blockquote-border); - color: var(--blockquote-text); - font-style: italic; -} - -hr { - height: 1px; - background-color: var(--blockquote-border); - border: none; /* removes default border */ -} - -/* ============================================ - Endnotes - ============================================ */ -section[role="doc-endnotes"] { - margin-top: 2em; - padding-top: 1em; - border-top: 1px solid var(--blockquote-border); -} - -section[role="doc-endnotes"] ol li a[role="doc-backlink"] { - padding-right: 0.2em; -} - -/* ============================================ - Responsive - ============================================ */ -@media (max-width: 600px) { - body { - padding: 12px; - font-size: 0.9em; - } -} diff --git a/src/rs/init.rs b/src/rs/init.rs index 1883435..c29a1ab 100644 --- a/src/rs/init.rs +++ b/src/rs/init.rs @@ -4,12 +4,12 @@ use tracing::info; use crate::Result; -const RHEO_TOML: &str = include_str!("../../examples/init_template/rheo.toml"); -const STYLE_CSS: &str = include_str!("../../examples/init_template/style.css"); -const INDEX_TYP: &str = include_str!("../../examples/init_template/content/index.typ"); -const ABOUT_TYP: &str = include_str!("../../examples/init_template/content/about.typ"); -const REFERENCES_BIB: &str = include_str!("../../examples/init_template/content/references.bib"); -const HEADER_SVG: &str = include_str!("../../examples/init_template/content/img/header.svg"); +const RHEO_TOML: &str = include_str!("../templates/init/rheo.toml"); +const STYLE_CSS: &str = include_str!("../templates/init/style.css"); +const INDEX_TYP: &str = include_str!("../templates/init/content/index.typ"); +const ABOUT_TYP: &str = include_str!("../templates/init/content/about.typ"); +const REFERENCES_BIB: &str = include_str!("../templates/init/content/references.bib"); +const HEADER_SVG: &str = include_str!("../templates/init/content/img/header.svg"); /// Initialize a new Rheo project at the given path. /// diff --git a/src/rs/output.rs b/src/rs/output.rs index 298ff54..e7148e2 100644 --- a/src/rs/output.rs +++ b/src/rs/output.rs @@ -80,7 +80,7 @@ impl OutputConfig { /// * `Err` if copying failed pub fn copy_html_assets(&self, project_style_css: Option<&Path>) -> Result<()> { // Default bundled CSS (embedded at compile time) - const DEFAULT_CSS: &str = include_str!("../css/style.css"); + const DEFAULT_CSS: &str = include_str!("../templates/init/style.css"); let dest_path = self.html_dir.join("style.css"); diff --git a/examples/init_template/content/about.typ b/src/templates/init/content/about.typ similarity index 100% rename from examples/init_template/content/about.typ rename to src/templates/init/content/about.typ diff --git a/examples/init_template/content/img/header.svg b/src/templates/init/content/img/header.svg similarity index 100% rename from examples/init_template/content/img/header.svg rename to src/templates/init/content/img/header.svg diff --git a/examples/init_template/content/index.typ b/src/templates/init/content/index.typ similarity index 100% rename from examples/init_template/content/index.typ rename to src/templates/init/content/index.typ diff --git a/examples/init_template/content/references.bib b/src/templates/init/content/references.bib similarity index 100% rename from examples/init_template/content/references.bib rename to src/templates/init/content/references.bib diff --git a/src/templates/init/rheo.toml b/src/templates/init/rheo.toml new file mode 100644 index 0000000..41233c7 --- /dev/null +++ b/src/templates/init/rheo.toml @@ -0,0 +1,11 @@ +version = "0.1.2" +content_dir = "content" + +[pdf.spine] +title = "rheo_project" +vertebrae = ["index.typ"] +merge = true + +[epub.spine] +title = "rheo_project" +vertebrae = ["index.typ", "about.typ"] diff --git a/examples/init_template/style.css b/src/templates/init/style.css similarity index 100% rename from examples/init_template/style.css rename to src/templates/init/style.css diff --git a/tests/harness.rs b/tests/harness.rs index a22a043..210cc28 100644 --- a/tests/harness.rs +++ b/tests/harness.rs @@ -15,7 +15,6 @@ use std::path::PathBuf; #[test_case("examples/blog_post")] #[test_case("examples/rheo_docs")] #[test_case("examples/fcl_site")] -#[test_case("examples/init_template")] #[test_case("examples/cover-letter.typ")] #[test_case("examples/blog_site/content/index.typ")] #[test_case("examples/blog_site/content/severance-ep-1.typ")] @@ -579,3 +578,70 @@ fn test_warning_formatting() { .args(["run", "--", "clean", test_dir.to_str().unwrap()]) .output(); } + +/// Test that `rheo init` creates a valid project that compiles successfully +#[test] +fn test_rheo_init_and_compile() { + let test_dir = PathBuf::from("tests/store/init_project"); + + // Clean previous test artifacts + if test_dir.exists() { + std::fs::remove_dir_all(&test_dir).expect("Failed to clean test dir"); + } + + // Run `rheo init` + let init_output = std::process::Command::new("cargo") + .args(["run", "--", "init", test_dir.to_str().unwrap()]) + .output() + .expect("Failed to run rheo init"); + + assert!( + init_output.status.success(), + "rheo init failed: {}", + String::from_utf8_lossy(&init_output.stderr) + ); + + // Verify expected files exist + assert!(test_dir.join("rheo.toml").exists(), "Missing rheo.toml"); + assert!(test_dir.join("style.css").exists(), "Missing style.css"); + assert!( + test_dir.join("content/index.typ").exists(), + "Missing content/index.typ" + ); + assert!( + test_dir.join("content/about.typ").exists(), + "Missing content/about.typ" + ); + + // Compile the initialized project + let build_dir = test_dir.join("build"); + let compile_output = std::process::Command::new("cargo") + .args([ + "run", + "--", + "compile", + test_dir.to_str().unwrap(), + "--build-dir", + build_dir.to_str().unwrap(), + ]) + .env("TYPST_IGNORE_SYSTEM_FONTS", "1") + .output() + .expect("Failed to run rheo compile"); + + assert!( + compile_output.status.success(), + "Compilation of init project failed: {}", + String::from_utf8_lossy(&compile_output.stderr) + ); + + // Verify outputs were created + assert!( + build_dir.join("html").exists(), + "HTML output directory missing" + ); + + // Clean up + if test_dir.exists() { + std::fs::remove_dir_all(&test_dir).ok(); + } +} diff --git a/tests/helpers/comparison.rs b/tests/helpers/comparison.rs index c14768e..50eb17e 100644 --- a/tests/helpers/comparison.rs +++ b/tests/helpers/comparison.rs @@ -124,7 +124,12 @@ where fn extract_build_relative_path(repo_relative_path: &str) -> PathBuf { let path = PathBuf::from(repo_relative_path); - let after_project = path.components().skip(2).collect::(); + let components: Vec<_> = path.components().collect(); + // If path has fewer than 3 components, it's already a build-relative path (e.g. "style.css") + if components.len() <= 2 { + return path; + } + let after_project = components.into_iter().skip(2).collect::(); after_project .strip_prefix("content") .unwrap_or(&after_project) diff --git a/tests/helpers/reference.rs b/tests/helpers/reference.rs index 22e4f79..009ef18 100644 --- a/tests/helpers/reference.rs +++ b/tests/helpers/reference.rs @@ -369,9 +369,9 @@ fn create_binary_metadata( }; // Detect source file location to create repo-relative path - // For CSS files, use the common source location since they're copied from src/css/ + // For CSS files, store the build-relative path directly (CSS is at the html root) let repo_relative_path = if filetype == "css" { - PathBuf::from("src/css").join(rel_path) + PathBuf::from(rel_path) } else if project_path.join("content").join(rel_path).exists() { project_path.join("content").join(rel_path) } else if project_path.join(rel_path).exists() { diff --git a/tests/ref/cases/pdf_merge/html/style.metadata.json b/tests/ref/cases/pdf_merge/html/style.metadata.json index f745872..bcc652f 100644 --- a/tests/ref/cases/pdf_merge/html/style.metadata.json +++ b/tests/ref/cases/pdf_merge/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", "file_size": 1080, - "path": "src/css/style.css", + "path": "style.css", "hash": "4d7f5be0d96185eadac50dc80ff33a0e3d435dac98b42929216b4311b589d6db" } \ No newline at end of file diff --git a/tests/ref/examples/blog_post/html/style.metadata.json b/tests/ref/examples/blog_post/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/examples/blog_post/html/style.metadata.json +++ b/tests/ref/examples/blog_post/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/examples/blog_site/html/style.metadata.json b/tests/ref/examples/blog_site/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/examples/blog_site/html/style.metadata.json +++ b/tests/ref/examples/blog_site/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/examples/code_blocks_with_links/html/style.metadata.json b/tests/ref/examples/code_blocks_with_links/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/examples/code_blocks_with_links/html/style.metadata.json +++ b/tests/ref/examples/code_blocks_with_links/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/examples/cross_directory_links/html/style.metadata.json b/tests/ref/examples/cross_directory_links/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/examples/cross_directory_links/html/style.metadata.json +++ b/tests/ref/examples/cross_directory_links/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/examples/epub_inferred_spine/html/style.metadata.json b/tests/ref/examples/epub_inferred_spine/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/examples/epub_inferred_spine/html/style.metadata.json +++ b/tests/ref/examples/epub_inferred_spine/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/examples/fcl_site/html/style.metadata.json b/tests/ref/examples/fcl_site/html/style.metadata.json index 988e531..8811419 100644 --- a/tests/ref/examples/fcl_site/html/style.metadata.json +++ b/tests/ref/examples/fcl_site/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", "file_size": 2460, - "path": "src/css/style.css", + "path": "style.css", "hash": "169fe62b2a7f5b66206fb764f6d63472b448f2ece5ecce642eb3a9a4b350dcd8" } \ No newline at end of file diff --git a/tests/ref/examples/init_template/epub/init_template.metadata.json b/tests/ref/examples/init_template/epub/init_template.metadata.json deleted file mode 100644 index ba80838..0000000 --- a/tests/ref/examples/init_template/epub/init_template.metadata.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "filetype": "epub", - "file_size": 5083, - "title": "rheo_project", - "language": "en", - "spine_files": [ - "index.xhtml", - "about.xhtml" - ], - "has_nav": true -} \ No newline at end of file diff --git a/tests/ref/examples/init_template/epub/xhtml/about.xhtml b/tests/ref/examples/init_template/epub/xhtml/about.xhtml deleted file mode 100644 index 544c733..0000000 --- a/tests/ref/examples/init_template/epub/xhtml/about.xhtml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - -
-

About

-

This project was built with Rheo.

- - -
\ No newline at end of file diff --git a/tests/ref/examples/init_template/epub/xhtml/index.xhtml b/tests/ref/examples/init_template/epub/xhtml/index.xhtml deleted file mode 100644 index 6cc88f6..0000000 --- a/tests/ref/examples/init_template/epub/xhtml/index.xhtml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - -
-

The philosophy of Rheo

-

Rheo is a prefix or combining form in English that originates from the Greek word rheos (ῥέος), meaning flow, stream, or current. Rheo flows Typst documents into a number of concurrent output formats in PDF, HTML, and EPUB. But other meanings lurk beneath the surface of this basic idea. Sarah Pourciau has argued that the oceanic is a deep-rooted metaphor in computing, as all computation at some level seeks solid space in a sea of digital noise (Pourciau 2022). From Alan Turing’s partial solution to David Hilbert’s Entscheidungsproblem in the universal machine, to Claude Shannon’s information theory, to Leslie Lamport’s ordering of events in a distributed system, the key issue at hand is how to carve out clarity from uncertainty and confusion. Writing has played a magisterial role in calming the storm of imprecise thought. Long before computation arrived on the scene, the written word has served as the steward of reason, in the Western world and beyond, from Mesopotamian cunieform to Twitter. Nota bene (‘Take note’): that writing can also herald chaos and confusion doesn’t invalidate its capacity for spreading sensibility.

-

Bibliography

-
-
    -
  • Pourciau, Sarah. 2022. “On the Digital Ocean.” Critical Inquiry 48 (2): 233–61. https://doi.org/10.1086/717319.
  • -
-
- - -
\ No newline at end of file diff --git a/tests/ref/examples/init_template/html/about.html b/tests/ref/examples/init_template/html/about.html deleted file mode 100644 index 6e1f322..0000000 --- a/tests/ref/examples/init_template/html/about.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - -
-
- -

About

-

This project was built with Rheo.

- - - \ No newline at end of file diff --git a/tests/ref/examples/init_template/html/index.html b/tests/ref/examples/init_template/html/index.html deleted file mode 100644 index 40cdff1..0000000 --- a/tests/ref/examples/init_template/html/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - -
-
- -

The philosophy of Rheo

-

Rheo is a prefix or combining form in English that originates from the Greek word rheos (ῥέος), meaning flow, stream, or current. Rheo flows Typst documents into a number of concurrent output formats in PDF, HTML, and EPUB. But other meanings lurk beneath the surface of this basic idea. Sarah Pourciau has argued that the oceanic is a deep-rooted metaphor in computing, as all computation at some level seeks solid space in a sea of digital noise (Pourciau 2022). From Alan Turing’s partial solution to David Hilbert’s Entscheidungsproblem in the universal machine, to Claude Shannon’s information theory, to Leslie Lamport’s ordering of events in a distributed system, the key issue at hand is how to carve out clarity from uncertainty and confusion. Writing has played a magisterial role in calming the storm of imprecise thought. Long before computation arrived on the scene, the written word has served as the steward of reason, in the Western world and beyond, from Mesopotamian cunieform to Twitter. Nota bene (‘Take note’): that writing can also herald chaos and confusion doesn’t invalidate its capacity for spreading sensibility.

-

Bibliography

-
-
    -
  • Pourciau, Sarah. 2022. “On the Digital Ocean.” Critical Inquiry 48 (2): 233–61. https://doi.org/10.1086/717319.
  • -
-
- - - \ No newline at end of file diff --git a/tests/ref/examples/init_template/html/style.metadata.json b/tests/ref/examples/init_template/html/style.metadata.json deleted file mode 100644 index 2ff4c00..0000000 --- a/tests/ref/examples/init_template/html/style.metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "filetype": "css", - "file_size": 2740, - "path": "src/css/style.css", - "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" -} \ No newline at end of file diff --git a/tests/ref/examples/init_template/pdf/init_template.metadata.json b/tests/ref/examples/init_template/pdf/init_template.metadata.json deleted file mode 100644 index bfa7b22..0000000 --- a/tests/ref/examples/init_template/pdf/init_template.metadata.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "filetype": "pdf", - "file_size": 6394, - "page_count": 1 -} \ No newline at end of file diff --git a/tests/ref/examples/link_path_edge_cases/html/style.metadata.json b/tests/ref/examples/link_path_edge_cases/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/examples/link_path_edge_cases/html/style.metadata.json +++ b/tests/ref/examples/link_path_edge_cases/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/examples/link_transformation/html/style.metadata.json b/tests/ref/examples/link_transformation/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/examples/link_transformation/html/style.metadata.json +++ b/tests/ref/examples/link_transformation/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/examples/links_with_fragments/html/style.metadata.json b/tests/ref/examples/links_with_fragments/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/examples/links_with_fragments/html/style.metadata.json +++ b/tests/ref/examples/links_with_fragments/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/examples/pdf_merge_false/html/style.metadata.json b/tests/ref/examples/pdf_merge_false/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/examples/pdf_merge_false/html/style.metadata.json +++ b/tests/ref/examples/pdf_merge_false/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/examples/relative_path_links/html/style.metadata.json b/tests/ref/examples/relative_path_links/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/examples/relative_path_links/html/style.metadata.json +++ b/tests/ref/examples/relative_path_links/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/epub/rheo_docs.metadata.json b/tests/ref/examples/rheo_docs/epub/rheo_docs.metadata.json index ef3dec9..ed0eb95 100644 --- a/tests/ref/examples/rheo_docs/epub/rheo_docs.metadata.json +++ b/tests/ref/examples/rheo_docs/epub/rheo_docs.metadata.json @@ -1,6 +1,6 @@ { "filetype": "epub", - "file_size": 52727, + "file_size": 52749, "title": "Rheo Manual", "language": "en", "spine_files": [ diff --git a/tests/ref/examples/rheo_docs/epub/xhtml/custom-css.xhtml b/tests/ref/examples/rheo_docs/epub/xhtml/custom-css.xhtml index 81b7f45..132d250 100644 --- a/tests/ref/examples/rheo_docs/epub/xhtml/custom-css.xhtml +++ b/tests/ref/examples/rheo_docs/epub/xhtml/custom-css.xhtml @@ -6,8 +6,8 @@ Custom CSS
-

When Rheo generates HTML, it injects a default stylesheet into the generated static site for a simple, modern, and mobile-friendly aesthetic. ‘Screening the subject’ is a website generated with the default Rheo stylesheet for reference.

-

You can fully customize the stylesheet by adding a style.css at the root of your project directory. Note that if your project contains a custom style.css, none of the styles in the default stylesheet will be applied. If you want to build on the default styles, copy and paste the default stylesheet into the style.css file in your project directory.

+

When Rheo generates HTML, it injects a default stylesheet into the generated static site for a simple, modern, and mobile-friendly aesthetic. ‘Screening the subject’ is a website generated with the default Rheo stylesheet for reference.

+

You can fully customize the stylesheet by adding a style.css at the root of your project directory. Note that if your project contains a custom style.css, none of the styles in the default stylesheet will be applied. If you want to build on the default styles, copy and paste the default stylesheet into the style.css file in your project directory.

\ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/custom-css.html b/tests/ref/examples/rheo_docs/html/custom-css.html index 56d11a9..c7d1e47 100644 --- a/tests/ref/examples/rheo_docs/html/custom-css.html +++ b/tests/ref/examples/rheo_docs/html/custom-css.html @@ -25,8 +25,8 @@
-

When Rheo generates HTML, it injects a default stylesheet into the generated static site for a simple, modern, and mobile-friendly aesthetic. ‘Screening the subject’ is a website generated with the default Rheo stylesheet for reference.

-

You can fully customize the stylesheet by adding a style.css at the root of your project directory. Note that if your project contains a custom style.css, none of the styles in the default stylesheet will be applied. If you want to build on the default styles, copy and paste the default stylesheet into the style.css file in your project directory.

+

When Rheo generates HTML, it injects a default stylesheet into the generated static site for a simple, modern, and mobile-friendly aesthetic. ‘Screening the subject’ is a website generated with the default Rheo stylesheet for reference.

+

You can fully customize the stylesheet by adding a style.css at the root of your project directory. Note that if your project contains a custom style.css, none of the styles in the default stylesheet will be applied. If you want to build on the default styles, copy and paste the default stylesheet into the style.css file in your project directory.

diff --git a/tests/ref/examples/rheo_docs/html/style.metadata.json b/tests/ref/examples/rheo_docs/html/style.metadata.json index 7cfcff7..3f3ec36 100644 --- a/tests/ref/examples/rheo_docs/html/style.metadata.json +++ b/tests/ref/examples/rheo_docs/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", "file_size": 10339, - "path": "src/css/style.css", + "path": "style.css", "hash": "941a9bc8b4b6f672fa89dcfa54f2426ea7a804d5c9dc4023cdfeeefe9102eb8d" } \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/pdf/rheo_docs.metadata.json b/tests/ref/examples/rheo_docs/pdf/rheo_docs.metadata.json index 881af9f..2827702 100644 --- a/tests/ref/examples/rheo_docs/pdf/rheo_docs.metadata.json +++ b/tests/ref/examples/rheo_docs/pdf/rheo_docs.metadata.json @@ -1,5 +1,5 @@ { "filetype": "pdf", - "file_size": 101683, + "file_size": 101727, "page_count": 5 } \ No newline at end of file diff --git a/tests/ref/examples/target_function/html/style.metadata.json b/tests/ref/examples/target_function/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/examples/target_function/html/style.metadata.json +++ b/tests/ref/examples/target_function/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/examples/target_function_in_module/html/style.metadata.json b/tests/ref/examples/target_function_in_module/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/examples/target_function_in_module/html/style.metadata.json +++ b/tests/ref/examples/target_function_in_module/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/examples/target_function_in_package/html/style.metadata.json b/tests/ref/examples/target_function_in_package/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/examples/target_function_in_package/html/style.metadata.json +++ b/tests/ref/examples/target_function_in_package/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/files/1d75da8a42d8f937/portable_epubs/html/style.metadata.json b/tests/ref/files/1d75da8a42d8f937/portable_epubs/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/files/1d75da8a42d8f937/portable_epubs/html/style.metadata.json +++ b/tests/ref/files/1d75da8a42d8f937/portable_epubs/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/files/6fdadcdcac7454ad/index/html/style.metadata.json b/tests/ref/files/6fdadcdcac7454ad/index/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/files/6fdadcdcac7454ad/index/html/style.metadata.json +++ b/tests/ref/files/6fdadcdcac7454ad/index/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/files/9a129f9c736a7947/severance-ep-1/html/style.metadata.json b/tests/ref/files/9a129f9c736a7947/severance-ep-1/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/files/9a129f9c736a7947/severance-ep-1/html/style.metadata.json +++ b/tests/ref/files/9a129f9c736a7947/severance-ep-1/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file diff --git a/tests/ref/files/f0b104671a707ab2/multiple_links_inline/html/style.metadata.json b/tests/ref/files/f0b104671a707ab2/multiple_links_inline/html/style.metadata.json index dbd27db..41624cc 100644 --- a/tests/ref/files/f0b104671a707ab2/multiple_links_inline/html/style.metadata.json +++ b/tests/ref/files/f0b104671a707ab2/multiple_links_inline/html/style.metadata.json @@ -1,6 +1,6 @@ { "filetype": "css", - "file_size": 2603, - "path": "src/css/style.css", - "hash": "02d37b0efd17dd8c8570eb1e3a71db78cde94f9de017e354aca839b6134ca93e" + "file_size": 2740, + "path": "style.css", + "hash": "fa215e69d8daf48f3c044f959d9071cceca24e0582656defd654cfd1581695ec" } \ No newline at end of file From 9186f32b69eff467fddac5efc4936709ea92c29d Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Wed, 11 Feb 2026 14:44:23 +0100 Subject: [PATCH 3/4] Removes submodule-based tests for rheo_docs and fcl_site --- .github/workflows/ci.yml | 2 - .github/workflows/pre-release.yml | 2 - .gitmodules | 7 -- tests/README.md | 34 -------- tests/harness.rs | 2 - .../fcl_site/epub/fcl_site.metadata.json | 10 --- .../examples/fcl_site/epub/xhtml/index.xhtml | 23 ----- tests/ref/examples/fcl_site/html/index.html | 21 ----- .../fcl_site/html/style.metadata.json | 6 -- .../fcl_site/pdf/fcl_site.metadata.json | 5 -- .../rheo_docs/epub/rheo_docs.metadata.json | 20 ----- .../rheo_docs/epub/xhtml/build-dir.xhtml | 22 ----- .../rheo_docs/epub/xhtml/content-dir.xhtml | 18 ---- .../rheo_docs/epub/xhtml/custom-css.xhtml | 13 --- .../examples/rheo_docs/epub/xhtml/faq.xhtml | 22 ----- .../rheo_docs/epub/xhtml/formats.xhtml | 26 ------ .../epub/xhtml/getting-started.xhtml | 59 ------------- .../examples/rheo_docs/epub/xhtml/index.xhtml | 33 ------- .../epub/xhtml/relative-linking.xhtml | 21 ----- .../rheo_docs/epub/xhtml/rheotoml.xhtml | 22 ----- .../rheo_docs/epub/xhtml/spines.xhtml | 26 ------ .../rheo_docs/epub/xhtml/why-is-rheo.xhtml | 37 -------- .../examples/rheo_docs/html/build-dir.html | 47 ---------- .../examples/rheo_docs/html/content-dir.html | 43 ---------- .../examples/rheo_docs/html/custom-css.html | 38 --------- .../examples/rheo_docs/html/endmatter.html | 7 -- tests/ref/examples/rheo_docs/html/faq.html | 47 ---------- .../ref/examples/rheo_docs/html/formats.html | 51 ----------- .../examples/rheo_docs/html/frontmatter.html | 7 -- .../rheo_docs/html/getting-started.html | 85 ------------------- tests/ref/examples/rheo_docs/html/index.html | 58 ------------- .../rheo_docs/html/relative-linking.html | 46 ---------- .../ref/examples/rheo_docs/html/rheotoml.html | 47 ---------- tests/ref/examples/rheo_docs/html/spines.html | 51 ----------- .../rheo_docs/html/style.metadata.json | 6 -- .../examples/rheo_docs/html/why-is-rheo.html | 62 -------------- .../rheo_docs/pdf/rheo_docs.metadata.json | 5 -- 37 files changed, 1031 deletions(-) delete mode 100644 .gitmodules delete mode 100644 tests/ref/examples/fcl_site/epub/fcl_site.metadata.json delete mode 100644 tests/ref/examples/fcl_site/epub/xhtml/index.xhtml delete mode 100644 tests/ref/examples/fcl_site/html/index.html delete mode 100644 tests/ref/examples/fcl_site/html/style.metadata.json delete mode 100644 tests/ref/examples/fcl_site/pdf/fcl_site.metadata.json delete mode 100644 tests/ref/examples/rheo_docs/epub/rheo_docs.metadata.json delete mode 100644 tests/ref/examples/rheo_docs/epub/xhtml/build-dir.xhtml delete mode 100644 tests/ref/examples/rheo_docs/epub/xhtml/content-dir.xhtml delete mode 100644 tests/ref/examples/rheo_docs/epub/xhtml/custom-css.xhtml delete mode 100644 tests/ref/examples/rheo_docs/epub/xhtml/faq.xhtml delete mode 100644 tests/ref/examples/rheo_docs/epub/xhtml/formats.xhtml delete mode 100644 tests/ref/examples/rheo_docs/epub/xhtml/getting-started.xhtml delete mode 100644 tests/ref/examples/rheo_docs/epub/xhtml/index.xhtml delete mode 100644 tests/ref/examples/rheo_docs/epub/xhtml/relative-linking.xhtml delete mode 100644 tests/ref/examples/rheo_docs/epub/xhtml/rheotoml.xhtml delete mode 100644 tests/ref/examples/rheo_docs/epub/xhtml/spines.xhtml delete mode 100644 tests/ref/examples/rheo_docs/epub/xhtml/why-is-rheo.xhtml delete mode 100644 tests/ref/examples/rheo_docs/html/build-dir.html delete mode 100644 tests/ref/examples/rheo_docs/html/content-dir.html delete mode 100644 tests/ref/examples/rheo_docs/html/custom-css.html delete mode 100644 tests/ref/examples/rheo_docs/html/endmatter.html delete mode 100644 tests/ref/examples/rheo_docs/html/faq.html delete mode 100644 tests/ref/examples/rheo_docs/html/formats.html delete mode 100644 tests/ref/examples/rheo_docs/html/frontmatter.html delete mode 100644 tests/ref/examples/rheo_docs/html/getting-started.html delete mode 100644 tests/ref/examples/rheo_docs/html/index.html delete mode 100644 tests/ref/examples/rheo_docs/html/relative-linking.html delete mode 100644 tests/ref/examples/rheo_docs/html/rheotoml.html delete mode 100644 tests/ref/examples/rheo_docs/html/spines.html delete mode 100644 tests/ref/examples/rheo_docs/html/style.metadata.json delete mode 100644 tests/ref/examples/rheo_docs/html/why-is-rheo.html delete mode 100644 tests/ref/examples/rheo_docs/pdf/rheo_docs.metadata.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ce12ba0..654af30 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,8 +13,6 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 - with: - submodules: recursive - name: Setup Rust toolchain uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 9730d80..cda996e 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -42,8 +42,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - submodules: recursive - name: Add target run: rustup target add ${{ matrix.target }} - name: Setup diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 17df4c9..0000000 --- a/.gitmodules +++ /dev/null @@ -1,7 +0,0 @@ -[submodule "examples/rheo_docs"] - path = examples/rheo_docs - url = https://github.com/freecomputinglab/rheo.ohrg.org - -[submodule "examples/fcl_site"] - path = examples/fcl_site - url = https://github.com/freecomputinglab/freecomputinglab.ohrg.org diff --git a/tests/README.md b/tests/README.md index b0d87a7..1854556 100644 --- a/tests/README.md +++ b/tests/README.md @@ -20,8 +20,6 @@ tests/ │ │ │ ├── pdf/ # Reference PDF metadata (*.metadata.json) │ │ │ └── epub/ # Reference EPUB metadata │ │ ├── blog_post/ -│ │ ├── rheo_docs/ -│ │ ├── fcl_site/ │ │ └── init_template/ │ ├── cases/ # Custom project tests │ └── files/ # Single-file tests @@ -49,38 +47,6 @@ cargo test --test harness cargo test -- --nocapture ``` -## Git Submodules - -This project includes external example repositories as git submodules: - -- `examples/rheo_docs` - Rheo documentation/manual - -### Setup - -After cloning the repository, initialize submodules before running tests: - -```bash -# Initialize submodules -git submodule update --init --recursive -``` - -### Updating Submodules - -To update submodules to the latest upstream version: - -```bash -# Update all submodules to latest -git submodule update --remote - -# Or update specific submodule -cd examples/rheo_docs -git pull origin main -cd ../.. -git add examples/rheo_docs -``` - -**Note**: While rheo uses Jujutsu (jj) for version control, git submodule commands must be used for submodule management. After using git commands for submodules, return to the normal jj workflow for committing changes. - ## Font Consistency To ensure tests produce identical output across different environments (local machines and CI), tests automatically use only Typst's embedded fonts. This prevents font-related rendering differences that cause page count and layout variations. diff --git a/tests/harness.rs b/tests/harness.rs index 210cc28..36271af 100644 --- a/tests/harness.rs +++ b/tests/harness.rs @@ -13,8 +13,6 @@ use std::path::PathBuf; #[test_case("examples/blog_site")] #[test_case("examples/blog_post")] -#[test_case("examples/rheo_docs")] -#[test_case("examples/fcl_site")] #[test_case("examples/cover-letter.typ")] #[test_case("examples/blog_site/content/index.typ")] #[test_case("examples/blog_site/content/severance-ep-1.typ")] diff --git a/tests/ref/examples/fcl_site/epub/fcl_site.metadata.json b/tests/ref/examples/fcl_site/epub/fcl_site.metadata.json deleted file mode 100644 index b785cf5..0000000 --- a/tests/ref/examples/fcl_site/epub/fcl_site.metadata.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "filetype": "epub", - "file_size": 1307924, - "title": "The Free Computing Lab", - "language": "en", - "spine_files": [ - "index.xhtml" - ], - "has_nav": true -} \ No newline at end of file diff --git a/tests/ref/examples/fcl_site/epub/xhtml/index.xhtml b/tests/ref/examples/fcl_site/epub/xhtml/index.xhtml deleted file mode 100644 index 832ccd7..0000000 --- a/tests/ref/examples/fcl_site/epub/xhtml/index.xhtml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - -
- -

The free computing lab researches the nature of computing freedom. Our research aims to demonstrate the role that the computer could and should play in a society where freedom is flourishing rather than deprecated, and to cultivate a critically grounded practice of software production, development, and maintenance.

-

See our GitHub page for code and more information. You can also join our Zulip to ask questions and follow our research, or drop us a note at hi@ohrg.org.

-

Our projects include:

- -
People
- -


- - -
\ No newline at end of file diff --git a/tests/ref/examples/fcl_site/html/index.html b/tests/ref/examples/fcl_site/html/index.html deleted file mode 100644 index c79052f..0000000 --- a/tests/ref/examples/fcl_site/html/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - -

The free computing lab researches the nature of computing freedom. Our research aims to demonstrate the role that the computer could and should play in a society where freedom is flourishing rather than deprecated, and to cultivate a critically grounded practice of software production, development, and maintenance.

-

See our GitHub page for code and more information. You can also join our Zulip to ask questions and follow our research, or drop us a note at hi@ohrg.org.

-

Our projects include:

- -
People
- -


- - - \ No newline at end of file diff --git a/tests/ref/examples/fcl_site/html/style.metadata.json b/tests/ref/examples/fcl_site/html/style.metadata.json deleted file mode 100644 index 8811419..0000000 --- a/tests/ref/examples/fcl_site/html/style.metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "filetype": "css", - "file_size": 2460, - "path": "style.css", - "hash": "169fe62b2a7f5b66206fb764f6d63472b448f2ece5ecce642eb3a9a4b350dcd8" -} \ No newline at end of file diff --git a/tests/ref/examples/fcl_site/pdf/fcl_site.metadata.json b/tests/ref/examples/fcl_site/pdf/fcl_site.metadata.json deleted file mode 100644 index b20c461..0000000 --- a/tests/ref/examples/fcl_site/pdf/fcl_site.metadata.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "filetype": "pdf", - "file_size": 8184, - "page_count": 1 -} \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/epub/rheo_docs.metadata.json b/tests/ref/examples/rheo_docs/epub/rheo_docs.metadata.json deleted file mode 100644 index ed0eb95..0000000 --- a/tests/ref/examples/rheo_docs/epub/rheo_docs.metadata.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "filetype": "epub", - "file_size": 52749, - "title": "Rheo Manual", - "language": "en", - "spine_files": [ - "index.xhtml", - "why-is-rheo.xhtml", - "getting-started.xhtml", - "relative-linking.xhtml", - "rheotoml.xhtml", - "build-dir.xhtml", - "content-dir.xhtml", - "formats.xhtml", - "spines.xhtml", - "custom-css.xhtml", - "faq.xhtml" - ], - "has_nav": true -} \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/epub/xhtml/build-dir.xhtml b/tests/ref/examples/rheo_docs/epub/xhtml/build-dir.xhtml deleted file mode 100644 index 3dc499a..0000000 --- a/tests/ref/examples/rheo_docs/epub/xhtml/build-dir.xhtml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - Build directory - -
-

Build directory

-

Rheo produces outputs in a simple directory structure with one subdirectory for each kind of output. By default, Rheo produces all outputs (PDF, HTML, and EPUB) in a build directory instide the project directory:

-
build/
├── epub
│   └── blog_post.epub
├── html
│   ├── portable_epubs.html
│   └── style.css
└── pdf
└── portable_epubs.pdf
-

The build directory path is calculated relative to the content directory. This is important, as if you change the content directory, then your build directory path will become relevant to that directory.

-

Configuration

-

CLI flag

-

You can specify a build directory with either the compile and watch commands:

-
rheo compile path/to/project --build-dir path/to/build
-

rheo.toml

-

The build directory is specified at the top level of the rheo.toml:

-
build_dir = "custom_build_directory"
- - -
\ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/epub/xhtml/content-dir.xhtml b/tests/ref/examples/rheo_docs/epub/xhtml/content-dir.xhtml deleted file mode 100644 index 8d7afbe..0000000 --- a/tests/ref/examples/rheo_docs/epub/xhtml/content-dir.xhtml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - Content directory - -
-

Content directory

-

By default, Rheo will search your entire project directory for Typst documents. You can, however, indicate a specific subdirectory that Rheo should use if you prefer. This can be helpful for structuring projects, as it allows you, for example, to keep a separate drafts folder that Rheo will not compile.

-

The default content directory is the same path as the Rheo project directory. It is important to note that if you specify a custom content directory, all other configuration such as build_dir and spine globs will operate relative to the content directory.

-

Configuration

-

rheo.toml

-

A custom content directory can be specified at the top level of the rheo.toml. The path is calculated relative to the project directory:

-
content_dir = "pages"
- - -
\ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/epub/xhtml/custom-css.xhtml b/tests/ref/examples/rheo_docs/epub/xhtml/custom-css.xhtml deleted file mode 100644 index 132d250..0000000 --- a/tests/ref/examples/rheo_docs/epub/xhtml/custom-css.xhtml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - Custom CSS - -
-

When Rheo generates HTML, it injects a default stylesheet into the generated static site for a simple, modern, and mobile-friendly aesthetic. ‘Screening the subject’ is a website generated with the default Rheo stylesheet for reference.

-

You can fully customize the stylesheet by adding a style.css at the root of your project directory. Note that if your project contains a custom style.css, none of the styles in the default stylesheet will be applied. If you want to build on the default styles, copy and paste the default stylesheet into the style.css file in your project directory.

- - -
\ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/epub/xhtml/faq.xhtml b/tests/ref/examples/rheo_docs/epub/xhtml/faq.xhtml deleted file mode 100644 index 819d61c..0000000 --- a/tests/ref/examples/rheo_docs/epub/xhtml/faq.xhtml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - Rheo - -
-

Frequently Asked Questions

-

What is the difference between Typst and Rheo?

-

Typst is a markup/programming language that provides its own toolchain which includes a CLI. You can use the Typst CLI to compile one Typst document to one kind of output file:

-
typst compile source.typ # compile to PDF
typst compile --features html --format html source.typ # compile to HTML
-

Rheo compiles a project folder to three outputs—PDF, HTML, and EPUB—concurrently. It allows you to configure how certain source files should be merged (to produce a ‘combined’ EPUB or PDF file, for example, via spines), and also allows you to enrich certain outputs (such as HTML via custom CSS) with non-Typst content. Rheo supports EPUB natively, which is not currently supported by the upstream Typst CLI (though it is on the roadmap). In summary, Rheo is a opinionated way to manage writing projects with Typst.

-

How do I read EPUBs on my system?

-

Mileage varies greatly on EPUB reading niceness across systems! If you’re interested to learn more, we have written more about this here. If you don’t have a good EPUB reading experience currently, we recommend trying bene, an EPUB reading system that we are developing.

-

Who maintains Rheo?

-

Rheo is developed by the Free Computing Lab, an academic research consortium that researches the nature of computing freedom. If you’re interested to learn more or get involved, you can join our Zulip.

-

Can I contribute to Rheo?

-

Yes! Rheo is written in Rust and developed in public through Github. You can track development and submit issues or requests for features through that platform. While in principle we welcome community pull requests, it’s best to join our Zulip and ask about it first, to confirm that your work will not go to waste.

- - -
\ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/epub/xhtml/formats.xhtml b/tests/ref/examples/rheo_docs/epub/xhtml/formats.xhtml deleted file mode 100644 index 7df3468..0000000 --- a/tests/ref/examples/rheo_docs/epub/xhtml/formats.xhtml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - Formats - -
-

Formats

-

By default, Rheo produces three different output formats simultaneously: PDF, HTML, and EPUB. There are cases in which you may only want to produce one of these formats, however, or to exclude one format because your project either cannot support or does not require it.

-

PDF

-

Typst, the programming language and compilation toolchain that underwrites Rheo, natively and fully supports PDF.

-

HTML

-

Typst experimentally supports HTML. This means that not all Typst syntax will translate to a meaningful HTML structure. The most common features in everyday prose are all supported, however, such as text markup, links, headings, footnotes, and citations. For more information on which features are currently supported in Typst’s HTML export, refer to the HTML export tracking issue.

-

EPUB

-

Typst does not yet support EPUB, but it is supported in Rheo. As EPUB export is on Typst’s roadmap, Rheo will track this feature closely and look to integrate with it when it lands in the future.

-

Configuration

-

CLI flag

-

You can constrain Rheo to producing one or more formats by passing one or more of the following flags to compile or watch:

-
rheo compile path/to/project --pdf
rheo compile path/to/project --html
rheo compile path/to/project --epub
-

rheo.toml

-

You can also specify formats at the top level of rheo.toml in an array that contains one or more formats. The default, if formats is not specified, is an array with all three formats:

-
formats = ["pdf", "html", "epub"] 
- - -
\ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/epub/xhtml/getting-started.xhtml b/tests/ref/examples/rheo_docs/epub/xhtml/getting-started.xhtml deleted file mode 100644 index a351883..0000000 --- a/tests/ref/examples/rheo_docs/epub/xhtml/getting-started.xhtml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - Getting started - -
-

Installation

-

The easiest way to install Rheo is from crates.io, the Rust language’s package manager. If you don’t already have Rust/cargo, you will need to install those first. Open your terminal, and run the following command:

-
cargo install rheo --locked
-

Rheo is packaged as a standalone binary, and doesn’t require any version of Typst on your system. (Note that even if you already have Typst on your system, Rheo will use its own embedded version of the compiler.) Refer to Rheo’s source code for more information and installation options.

-

Firing up

-

With Rheo we can produce a static site, a PDF, and an EPUB from a Typst document. Let’s create a directory with a single Typst file in it:

-
mkdir project_uno
touch project_uno/index.typ
-

As one of Rheo’s outputs is a static site, the landing page will default to one named ‘index’. (If this file doesn’t exist, Rheo will present you with a basic listing of all the other files in the site.) Let’s put some Typst in the index.typ file:

-

project_uno/index.typ

-
= Project uno

Project uno is a writing project.
-

Rheo aims to keep out of your way as much as possible, and doesn’t require that you add any special syntax or metadata to your files to work. This single Typst file we need to get started. Provided you’ve already installed Rheo on your system, we can compile the project. You can tell Rheo to compile a folder by pointing the compile command at it:

-
rheo compile project_uno 
-

This command produces a build subdirectory inside the base directory which contains a PDF, an EPUB, and a static site (HTML and CSS). Your project folder should now look like so:

-
.
├── build
│   ├── epub
│   │   └── project_uno.epub
│   ├── html
│   │   ├── index.html
│   │   └── style.css
│   └── pdf
│   └── index.pdf
└── index.typ
-

It’s a little tiring to have to run the compile command every time we make a change, though. Let’s spin up a development server to see live changes across all output formats as we edit the source:

-
rheo watch project_uno --open
-

The --open flag here indicates that we’d like to open the output using our system’s default applications. Provided you have an EPUB reader on your system (if you don’t, we recommend installing bene), you should now have a PDF, an EPUB, and a website in front of you. As simple as that!

-

Scaling up

-

Let’s kill that process (with Ctrl-C). Rheo compiles documents from across your project directory towards EPUB, PDF, and HTML simultaneously, whereas the Typst compiler typically takes just one Typst file and produces one kind of output.1 Let’s add a couple of files to our project and link between them:

-

project_uno/about.typ

-
= About

Project uno is an incredible writing project that will transform the way we understand the world.
If you want to be involved, see the #link("./contact.typ")[Contact page].
-

project_uno/contact.typ

-
#let email = "myemail@mydomain.com"
= Contact

To learn more about project uno, email me at #link("mailto:" + email)[#email]
-

And let’s also link to the two new pages on the index page:

-

project_uno/index.typ

-
= Project uno

Project uno is a writing project.

- #link("./about.typ")[About]
- #link("./contact.typ")[Contact]
-

Now let’s run Rheo again, but this time let’s only build the HTML and EPUB outputs:

-
rheo watch project_uno --html --epub --open
-

Note how the relative links are working across both the EPUB and the PDF. Relative linking is one of the key features in Rheo that enables you to build richer static sites and EPUBs beyond using just Typst. All of Typst’s other features such as variables are fair game, too, as Rheo just uses Typst’s compiler under the hood.

-

Adding a config

-

One issue with the EPUB that is currently being produced is that the index.typ section shows up last, after the about.typ and contact.typ, as Rheo orders files lexicographically by default. This is probably not what we want, as the index page acts as a sort of table of contents in our writing project currently.

-

To sophisticate the way that Rheo produces outputs, we can add a rheo.toml config at the base of the project directory:

-

project_uno/rheo.toml

-
version = "0.1.0"

[epub.spine]
title = "Project Uno"
vertebrae = ["index.typ", "about.typ", "contact.typ"]
-

This config uses the notion of a spine to indicate a custom order for the sections. We’ll learn more about these later on in this documentation.

-

Let’s run the watch command again, this time with all outputs like the first time:

-
rheo watch project_uno --open
-

Great! The EPUB order is fixed. We now, however, have three distinct PDFs that are being created: one for each page. This is because Rheo defaults to producing one PDF per file in the project directory. We can configure Rheo to merge files together into a single PDF output by specifying a PDF spine, as we did with EPUB, and setting the merge attribute to true:

-

project_uno/rheo.toml

-
version = "0.1.0"

[epub.spine]
title = "Project Uno"
vertebrae = ["index.typ", "about.typ", "contact.typ"]

[pdf.spine]
title = "Project Uno"
vertebrae = ["index.typ", "about.typ", "contact.typ"]
merge = true
-

Before we run this again, let’s also clean the outputs in the build directory, as we don’t need those individual PDFs that we produced anymore:

-
rheo clean project_uno
rheo watch project_uno --open
-

Now we have a fully featured writing project, with nice-looking and orderly outputs in PDF, EPUB, and in HTML!

-
-
    -
  1. 1Typst allows you to break up your projects using modules, but still requires one entrypoint. Rheo, by contrast, enables multiple entrypoint files, corresponding to multiple standalone pages in a static site.
  2. -
-
- - -
\ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/epub/xhtml/index.xhtml b/tests/ref/examples/rheo_docs/epub/xhtml/index.xhtml deleted file mode 100644 index 049518e..0000000 --- a/tests/ref/examples/rheo_docs/epub/xhtml/index.xhtml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - Introduction - -
-

What is Rheo?

-

The simple answer is that Rheo (ree-oh) is a new and more flexible way to produce and publish digital documents. The less simple answer is that Rheo is a typesetting and static site engine based on Typst. This guide explains both how to use Rheo, and why it might be for you.

-

Rheo allows you to produce a website, a fixed-size document, and an adaptive document from a single set of source Typst files. It allows you to do something similar to LaTeX—except that Typst is much simpler to write, and we can produce a greater number of formats with it. The documentation that you are reading now, for example, was typeset with Rheo. As a result, you can read it as:

-
    -
  • HTML - as a website for browsers.
  • -
  • PDF - as a fixed-size document for printing.
  • -
  • EPUB - as an adaptive document for e-readers.
  • -
-

Who should use Rheo?

-

If you write anything as simple as a blog or as complex as a dissertation or monograph in Typst, Rheo enables you to publish it in multiple formats. If you are willing to learn a little bit of syntax, you can turn a piece of writing into a website, an adaptive document, and/or a printable document.

-

Some of the things you can write and publish with Rheo include:

-
    -
  • A blog
  • -
  • A paper
  • -
  • A dissertation
  • -
  • A book manuscript
  • -
  • A novel
  • -
  • A textbook
  • -
  • Technical documentation
  • -
-

Rheo is for anyone who has ever spent regrettable hours formatting citatons, fighting with LaTeX, who has experienced the limitations of Markdown, or who wants to benefit from the richer writing experience that Typst makes possible (more on this in the next section). It is for students and teachers, humanists and scientists, bloggers and novelists.

-

If you have only ever used Microsoft Word to author text, or haven’t heard the phrase ‘markup language’ before, we recommend first familiarizing yourself with Typst via the excellent tutorial. This should give you a good intuition for what Typst is—a markup language similar to but also more powerful than Markdown—and why you might want to use Rheo to typeset your documents.

- - -
\ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/epub/xhtml/relative-linking.xhtml b/tests/ref/examples/rheo_docs/epub/xhtml/relative-linking.xhtml deleted file mode 100644 index e9bf294..0000000 --- a/tests/ref/examples/rheo_docs/epub/xhtml/relative-linking.xhtml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - Relative linking - -
-

Rheo allows you to write documents in plain Typst without requiring any additional syntax or metadata. Because Rheo can combine multiple files into unified outputs, however, we need a way to reference other files in the same Rheo project.

-

The syntax for these relative links in Rheo should be familiar, as they look just like regular Typst links, but reference a .typ file in the same directory as its target:

-
#link("./another-section.typ")[Another section]
-

When you compile a project with Rheo, relative links to other Typst documents in the same directory will be resolved and transformed according to the output format. What a relative link transforms to depends on both the output format and your Rheo configuration, as using features such as spines affects the control flow between your source Typst and output formats.

-
    -
  • In HTML, relative links become <a> tags that point to the relevant html page.
  • -
  • In PDF, relative links either become plain text (if input Typst is not combined, and thus produces one PDF per source document), or links to the relevant sections in the output document (if your config specifies a spine with the merge attribute set).
  • -
  • In EPUB, relative links become links to the relevant sections in the EPUB.
  • -
-

Relative linking is what allows Rheo to produce fully functional static sites. It is also a feature that you can use to help you organize large writing projects. (Note that the Typst import keyword works as you would expect in Rheo, and so can also/still be used as a mechanism to modularize projects.)

- - -
\ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/epub/xhtml/rheotoml.xhtml b/tests/ref/examples/rheo_docs/epub/xhtml/rheotoml.xhtml deleted file mode 100644 index aec6c5e..0000000 --- a/tests/ref/examples/rheo_docs/epub/xhtml/rheotoml.xhtml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - Rheo.toml - -
-

Rheo is a CLI that produces PDF, HTML, and EPUB simultaneously from a directory of Typst source documents. The directory that contains your Typst is called the project directory, and you can compile it like so:

-
rheo compile path/to/projectdirectory
-

In general, there are two ways to configure Rheo:

-
    -
  1. By passing flags directly to the CLI command.
  2. -
  3. By specifying configuration in a rheo.toml file at the root of the project directory.
  4. -
-

If you compile a Rheo project directory without a rheo.toml file, the following default settings will be applied to compile your project.

-
version = "0.1.0"
content_dir = "./"
build_dir = "build"
formats = ["pdf", "html", "epub"]

[epub.spine]
vertebrae = ["**/*.typ"]
title = "[project directory name]"
-

To point Rheo to a rheo.toml file that is not at the root of the project directory, specify it directly via the CLI:

-
rheo compile path/to/project --config path/to/config 
- - -
\ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/epub/xhtml/spines.xhtml b/tests/ref/examples/rheo_docs/epub/xhtml/spines.xhtml deleted file mode 100644 index a3449e6..0000000 --- a/tests/ref/examples/rheo_docs/epub/xhtml/spines.xhtml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - Spines - -
-

Spines

-

A spine in Rheo is the backbone or ‘table of contents’ of Typst source files that should be compiled to an output format. It takes its name from the epub specification, in which the spine articulates—or reticulates— the set and order of chapters included.

-

You can specify a spine’s vertebrae for any output format using an array of glob strings in rheo.toml:

-
[epub.spine]
title = "My epub"
vertebrae = ["intro.typ", "*.typ"]
-

Notice how the first entry intro.typ is a specific file, whereas the second *.typ captures a range of files. When a glob string captures a range of source files, they will be ordered lexicographically in the spine.

-

EPUB

-

An EPUB must have a spine in order to be valid. By default, Rheo will infer the following spine if not specified:

-
[epub.spine]
title = "[project folder name]"
vertebrae = ["**/*.typ"]
-

PDF

-

By default, Rheo generates one PDF per Typst source file. You can specify a spine for the PDF format in order to reticulate multiple source documents into a single output PDF by indicating the vertebrae and setting merge to true:

-
[pdf.spine]
title = "My reticulated pdf"
vertebrae = ["intro.typ", "*.typ"]
merge = true
-

In a PDF generated in this way, relative links will resolve to internal document links that point to the relevant section.

-

HTML

-

Rheo does not currently support customizing HTML spines. The default spine uses all Typst files:

-
[html.spine]
title = "[project folder name]"
vertebrae = ["**/*.typ"]
- - -
\ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/epub/xhtml/why-is-rheo.xhtml b/tests/ref/examples/rheo_docs/epub/xhtml/why-is-rheo.xhtml deleted file mode 100644 index d8b3fe9..0000000 --- a/tests/ref/examples/rheo_docs/epub/xhtml/why-is-rheo.xhtml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - Why Rheo? - -
-

Why do we need Rheo?

-

Rheo (ree-oh) is an open source typesetting and static site engine for Typst. It is a typesetting engine because it produces typeset digital documents such as PDF and EPUB, and a static site engine because it produces websites that don’t require communication with a custom backend server, but rather are self-sufficient sets of files that can be natively opened a browser (static sites). Most static site engines these days employ Markdown, a markup format that is approachable and pretty generic, allowing folks who are not familiar with or otherwise don’t want to deal directly with the required file formats of the web— HTML, CSS, and Javascript— to write blog posts and other content which can then be pumped into a static site.

-

As useful as it is, Markdown has its ambiguities. For one, there isn’t a standardized syntax for citations or footnotes. Though extensions exist that can produce these, they are not supported in the core Markdown syntax, meaning that it’s not really Markdown and can’t be relied upon to work in all contexts that support Markdown. Markdown is great when using hypertext (hyperlinks, images, etc). It’s not so great when it comes to things like tables, figures, and math.

-

Typst is a markup language that integrates with plain text, like Markdown, making it easy to adopt and joyful to write. Unlike Markdown, however, it is also a Turing-complete programming language with a modern type system, meaning that it is possible (though not necessary) to express sophisticated conditional logic controlling where and how text is rendered. Typst has a concrete and concise syntax for footnotes and citations, and can express visual constructs such as tables, figures, colors, and mathematical formulas. It was developed as a modern alternative to LaTeX, Leslie Lamport’s legendary 1980s addition to Donald Knuth’s original ‘78 Tex typesetting system. For the past 40 years, LaTeX has been the most expressive way to produce PDF documents, rendering it the de facto standard for academic and scientific publication. In the past few years, Typst has become the most promising and powerful alternative to LaTeX due to its maintainers’ effort to build out a reliable PDF compilation toolchain.

-

In 2025, Typst added experimental support for HTML compilation. Though there are still many features in Typst that will only produce meaningful output in the PDF toolchain, the HTML toolchain now supports all of the essential features for academic documents in the humanities: text decoration, headings, hyperlinks, footnotes, and citations.1 This makes it an extremely good replacement for Markdown as a markup language in a static site engine, and so: enter Rheo.

-

Rheo is a CLI (command line interface) that produces PDF, HTML, and EPUB simultaneously from a folder of Typst documents. It is a static site engine because it can produce a fully valid website: all it needs is a folder containing valid Typst. Rheo also provides mechanisms to combine multiple Typst files into a unified EPUB or PDF, making it a tool that improves the experience of writing books, dissertations, or any other long-form text in Typst. On the other side of the same coin, Rheo allows you to produce an offline version of a website such as a blog written in Typst through its PDF/EPUB toolchain.

-

Rheo allows you to compile multiple Typst files that link to each other into a single output, adding what is needed (relative linking) in order to make Typst an ideal markup language for writing static sites. Typst is the most elegant and flexible way to typeset PDF documents today; Rheo extends Typst’s capabilities, allowing you to additionally typeset EPUBs and generate static sites from the same source.2 Naturally, this blog post was written in Typst, and this site was made with Rheo. If you’re already convinced, feel free to jump ahead to Getting Started to download Rheo on your system and start writing.

-

The philosophy of Rheo

-

Rheo is a prefix or combining form in English that originates from the Greek word rheos (ῥέος), meaning flow, stream, or current. Rheo flows Typst documents into a number of concurrent output formats in PDF, HTML, and EPUB. But other meanings lurk beneath the surface of this basic idea. Sarah Pourciau has argued that the oceanic is a deep-rooted metaphor in computing, as all computation at some level seeks solid space in a sea of digital noise (Pourciau 2022). From Alan Turing’s partial solution to David Hilbert’s Entscheidungsproblem in the universal machine, to Claude Shannon’s information theory, to Leslie Lamport’s ordering of events in a distributed system, the key issue at hand is how to carve out clarity from uncertainty and confusion. Writing has played a magisterial role in calming the storm of imprecise thought. Long before computation arrived on the scene, the written word has served as the steward of reason, in the Western world and beyond, from Mesopotamian cunieform to Twitter. Nota bene (‘Take note’): that writing can also herald chaos and confusion doesn’t invalidate its capacity for spreading sensibility.

-

Rheo is a tool that facilitates the production and publication of documents following from the original vision of the Internet as a mechanism for lively and reasonably unfettered academic exchange, rather than the densely commercial space of platform capitalism that it has become. It should not be so difficult, given the extraordinary capacities of software and hardware today, to make a piece of writing publically available in a plain and pleasant format. That there exist digital humanities initiatives measured in months and years to bring books to the web as basic websites is a clear sign that something has gone awry.3

-

Rheo aims to enable the publication of more books, blog posts, and papers without the necessary capitalist ceremony of creating an account on Substack, Medium, or Squarespace. A website without any interactive elements such as forms, online marketplaces, or comments should be simple to set up, as it isn’t rocket science in 2025 thanks to all the hard work that folks have put into Internet protocols and web standards. It should be simple to create a PDF or EPUB for sharing with colleagues or collaborators—as simple as it is to send an email.

-

This is the vision of the world to which we at the free computing lab aspire, and in search of which we have built Rheo. Rheo is the first installment in a larger set of writing tools we aim to build, which will include processes for collaboratively drafting documents, constructing and working with digital libraries, and more.

-

Bibliography

-
-
    -
  • Pourciau, Sarah. 2022. “On the Digital Ocean.” Critical Inquiry 48 (2): 233–61. https://doi.org/10.1086/717319.
  • -
-
-

Footnotes

-
-
    -
  1. 1 I qualify this with ‘in the humanities’ as scientific papers often require tables, figures, and mathematical markup. These features are on Typst’s roadmap for html, but are not yet available at time of writing (January 2026).
  2. -
  3. 2EPUB is on Typst’s roadmap, but is not yet natively supported.
  4. -
  5. 3 There are many exciting and experimental ways of presenting text and other conent in the digital humanities. But we think that it should be easier that it currently is to publish and distribute books digitally, simply and straightforwardly.
  6. -
-
- - -
\ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/build-dir.html b/tests/ref/examples/rheo_docs/html/build-dir.html deleted file mode 100644 index 1dd80db..0000000 --- a/tests/ref/examples/rheo_docs/html/build-dir.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - Build directory - - -
- -

Rheo

-
- -
-

Build directory

-

Rheo produces outputs in a simple directory structure with one subdirectory for each kind of output. By default, Rheo produces all outputs (PDF, HTML, and EPUB) in a build directory instide the project directory:

-
build/
├── epub
│   └── blog_post.epub
├── html
│   ├── portable_epubs.html
│   └── style.css
└── pdf
└── portable_epubs.pdf
-

The build directory path is calculated relative to the content directory. This is important, as if you change the content directory, then your build directory path will become relevant to that directory.

-

Configuration

-

CLI flag

-

You can specify a build directory with either the compile and watch commands:

-
rheo compile path/to/project --build-dir path/to/build
-

rheo.toml

-

The build directory is specified at the top level of the rheo.toml:

-
build_dir = "custom_build_directory"
-
- - - - - - \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/content-dir.html b/tests/ref/examples/rheo_docs/html/content-dir.html deleted file mode 100644 index b0b3fc6..0000000 --- a/tests/ref/examples/rheo_docs/html/content-dir.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - Content directory - - -
- -

Rheo

-
- -
-

Content directory

-

By default, Rheo will search your entire project directory for Typst documents. You can, however, indicate a specific subdirectory that Rheo should use if you prefer. This can be helpful for structuring projects, as it allows you, for example, to keep a separate drafts folder that Rheo will not compile.

-

The default content directory is the same path as the Rheo project directory. It is important to note that if you specify a custom content directory, all other configuration such as build_dir and spine globs will operate relative to the content directory.

-

Configuration

-

rheo.toml

-

A custom content directory can be specified at the top level of the rheo.toml. The path is calculated relative to the project directory:

-
content_dir = "pages"
-
- - - - - - \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/custom-css.html b/tests/ref/examples/rheo_docs/html/custom-css.html deleted file mode 100644 index c7d1e47..0000000 --- a/tests/ref/examples/rheo_docs/html/custom-css.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - Custom CSS - - -
- -

Rheo

-
- -
-

When Rheo generates HTML, it injects a default stylesheet into the generated static site for a simple, modern, and mobile-friendly aesthetic. ‘Screening the subject’ is a website generated with the default Rheo stylesheet for reference.

-

You can fully customize the stylesheet by adding a style.css at the root of your project directory. Note that if your project contains a custom style.css, none of the styles in the default stylesheet will be applied. If you want to build on the default styles, copy and paste the default stylesheet into the style.css file in your project directory.

-
- - - - - - \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/endmatter.html b/tests/ref/examples/rheo_docs/html/endmatter.html deleted file mode 100644 index fcf9151..0000000 --- a/tests/ref/examples/rheo_docs/html/endmatter.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/faq.html b/tests/ref/examples/rheo_docs/html/faq.html deleted file mode 100644 index 24c828a..0000000 --- a/tests/ref/examples/rheo_docs/html/faq.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - Rheo - - -
- -

Rheo

-
- -
-

Frequently Asked Questions

-

What is the difference between Typst and Rheo?

-

Typst is a markup/programming language that provides its own toolchain which includes a CLI. You can use the Typst CLI to compile one Typst document to one kind of output file:

-
typst compile source.typ # compile to PDF
typst compile --features html --format html source.typ # compile to HTML
-

Rheo compiles a project folder to three outputs—PDF, HTML, and EPUB—concurrently. It allows you to configure how certain source files should be merged (to produce a ‘combined’ EPUB or PDF file, for example, via spines), and also allows you to enrich certain outputs (such as HTML via custom CSS) with non-Typst content. Rheo supports EPUB natively, which is not currently supported by the upstream Typst CLI (though it is on the roadmap). In summary, Rheo is a opinionated way to manage writing projects with Typst.

-

How do I read EPUBs on my system?

-

Mileage varies greatly on EPUB reading niceness across systems! If you’re interested to learn more, we have written more about this here. If you don’t have a good EPUB reading experience currently, we recommend trying bene, an EPUB reading system that we are developing.

-

Who maintains Rheo?

-

Rheo is developed by the Free Computing Lab, an academic research consortium that researches the nature of computing freedom. If you’re interested to learn more or get involved, you can join our Zulip.

-

Can I contribute to Rheo?

-

Yes! Rheo is written in Rust and developed in public through Github. You can track development and submit issues or requests for features through that platform. While in principle we welcome community pull requests, it’s best to join our Zulip and ask about it first, to confirm that your work will not go to waste.

-
- - - - - - \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/formats.html b/tests/ref/examples/rheo_docs/html/formats.html deleted file mode 100644 index a7e9641..0000000 --- a/tests/ref/examples/rheo_docs/html/formats.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - Formats - - -
- -

Rheo

-
- -
-

Formats

-

By default, Rheo produces three different output formats simultaneously: PDF, HTML, and EPUB. There are cases in which you may only want to produce one of these formats, however, or to exclude one format because your project either cannot support or does not require it.

-

PDF

-

Typst, the programming language and compilation toolchain that underwrites Rheo, natively and fully supports PDF.

-

HTML

-

Typst experimentally supports HTML. This means that not all Typst syntax will translate to a meaningful HTML structure. The most common features in everyday prose are all supported, however, such as text markup, links, headings, footnotes, and citations. For more information on which features are currently supported in Typst’s HTML export, refer to the HTML export tracking issue.

-

EPUB

-

Typst does not yet support EPUB, but it is supported in Rheo. As EPUB export is on Typst’s roadmap, Rheo will track this feature closely and look to integrate with it when it lands in the future.

-

Configuration

-

CLI flag

-

You can constrain Rheo to producing one or more formats by passing one or more of the following flags to compile or watch:

-
rheo compile path/to/project --pdf
rheo compile path/to/project --html
rheo compile path/to/project --epub
-

rheo.toml

-

You can also specify formats at the top level of rheo.toml in an array that contains one or more formats. The default, if formats is not specified, is an array with all three formats:

-
formats = ["pdf", "html", "epub"] 
-
- - - - - - \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/frontmatter.html b/tests/ref/examples/rheo_docs/html/frontmatter.html deleted file mode 100644 index fcf9151..0000000 --- a/tests/ref/examples/rheo_docs/html/frontmatter.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/getting-started.html b/tests/ref/examples/rheo_docs/html/getting-started.html deleted file mode 100644 index 6a4f8ab..0000000 --- a/tests/ref/examples/rheo_docs/html/getting-started.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - Getting started - - -
- -

Rheo

-
- -
-

Installation

-

The easiest way to install Rheo is from crates.io, the Rust language’s package manager. If you don’t already have Rust/cargo, you will need to install those first. Open your terminal, and run the following command:

-
cargo install rheo --locked
-

Rheo is packaged as a standalone binary, and doesn’t require any version of Typst on your system. (Note that even if you already have Typst on your system, Rheo will use its own embedded version of the compiler.) Refer to Rheo’s source code for more information and installation options.

-

Firing up

-

With Rheo we can produce a static site, a PDF, and an EPUB from a Typst document. Let’s create a directory with a single Typst file in it:

-
mkdir project_uno
touch project_uno/index.typ
-

As one of Rheo’s outputs is a static site, the landing page will default to one named ‘index’. (If this file doesn’t exist, Rheo will present you with a basic listing of all the other files in the site.) Let’s put some Typst in the index.typ file:

-

project_uno/index.typ

-
= Project uno

Project uno is a writing project.
-

Rheo aims to keep out of your way as much as possible, and doesn’t require that you add any special syntax or metadata to your files to work. This single Typst file we need to get started. Provided you’ve already installed Rheo on your system, we can compile the project. You can tell Rheo to compile a folder by pointing the compile command at it:

-
rheo compile project_uno 
-

This command produces a build subdirectory inside the base directory which contains a PDF, an EPUB, and a static site (HTML and CSS). Your project folder should now look like so:

-
.
├── build
│   ├── epub
│   │   └── project_uno.epub
│   ├── html
│   │   ├── index.html
│   │   └── style.css
│   └── pdf
│   └── index.pdf
└── index.typ
-

It’s a little tiring to have to run the compile command every time we make a change, though. Let’s spin up a development server to see live changes across all output formats as we edit the source:

-
rheo watch project_uno --open
-

The --open flag here indicates that we’d like to open the output using our system’s default applications. Provided you have an EPUB reader on your system (if you don’t, we recommend installing bene), you should now have a PDF, an EPUB, and a website in front of you. As simple as that!

-

Scaling up

-

Let’s kill that process (with Ctrl-C). Rheo compiles documents from across your project directory towards EPUB, PDF, and HTML simultaneously, whereas the Typst compiler typically takes just one Typst file and produces one kind of output.1 Let’s add a couple of files to our project and link between them:

-

project_uno/about.typ

-
= About

Project uno is an incredible writing project that will transform the way we understand the world.
If you want to be involved, see the #link("./contact.typ")[Contact page].
-

project_uno/contact.typ

-
#let email = "myemail@mydomain.com"
= Contact

To learn more about project uno, email me at #link("mailto:" + email)[#email]
-

And let’s also link to the two new pages on the index page:

-

project_uno/index.typ

-
= Project uno

Project uno is a writing project.

- #link("./about.typ")[About]
- #link("./contact.typ")[Contact]
-

Now let’s run Rheo again, but this time let’s only build the HTML and EPUB outputs:

-
rheo watch project_uno --html --epub --open
-

Note how the relative links are working across both the EPUB and the PDF. Relative linking is one of the key features in Rheo that enables you to build richer static sites and EPUBs beyond using just Typst. All of Typst’s other features such as variables are fair game, too, as Rheo just uses Typst’s compiler under the hood.

-

Adding a config

-

One issue with the EPUB that is currently being produced is that the index.typ section shows up last, after the about.typ and contact.typ, as Rheo orders files lexicographically by default. This is probably not what we want, as the index page acts as a sort of table of contents in our writing project currently.

-

To sophisticate the way that Rheo produces outputs, we can add a rheo.toml config at the base of the project directory:

-

project_uno/rheo.toml

-
version = "0.1.0"

[epub.spine]
title = "Project Uno"
vertebrae = ["index.typ", "about.typ", "contact.typ"]
-

This config uses the notion of a spine to indicate a custom order for the sections. We’ll learn more about these later on in this documentation.

-

Let’s run the watch command again, this time with all outputs like the first time:

-
rheo watch project_uno --open
-

Great! The EPUB order is fixed. We now, however, have three distinct PDFs that are being created: one for each page. This is because Rheo defaults to producing one PDF per file in the project directory. We can configure Rheo to merge files together into a single PDF output by specifying a PDF spine, as we did with EPUB, and setting the merge attribute to true:

-

project_uno/rheo.toml

-
version = "0.1.0"

[epub.spine]
title = "Project Uno"
vertebrae = ["index.typ", "about.typ", "contact.typ"]

[pdf.spine]
title = "Project Uno"
vertebrae = ["index.typ", "about.typ", "contact.typ"]
merge = true
-

Before we run this again, let’s also clean the outputs in the build directory, as we don’t need those individual PDFs that we produced anymore:

-
rheo clean project_uno
rheo watch project_uno --open
-

Now we have a fully featured writing project, with nice-looking and orderly outputs in PDF, EPUB, and in HTML!

-

Footnotes

-
- - - -
-
    -
  1. 1Typst allows you to break up your projects using modules, but still requires one entrypoint. Rheo, by contrast, enables multiple entrypoint files, corresponding to multiple standalone pages in a static site.
  2. -
-
- - - \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/index.html b/tests/ref/examples/rheo_docs/html/index.html deleted file mode 100644 index 954d8d0..0000000 --- a/tests/ref/examples/rheo_docs/html/index.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - Introduction - - -
- -

Rheo

-
- -
-

What is Rheo?

-

The simple answer is that Rheo (ree-oh) is a new and more flexible way to produce and publish digital documents. The less simple answer is that Rheo is a typesetting and static site engine based on Typst. This guide explains both how to use Rheo, and why it might be for you.

-

Rheo allows you to produce a website, a fixed-size document, and an adaptive document from a single set of source Typst files. It allows you to do something similar to LaTeX—except that Typst is much simpler to write, and we can produce a greater number of formats with it. The documentation that you are reading now, for example, was typeset with Rheo. As a result, you can read it as:

-
    -
  • HTML - as a website for browsers.
  • -
  • PDF - as a fixed-size document for printing.
  • -
  • EPUB - as an adaptive document for e-readers.
  • -
-

Who should use Rheo?

-

If you write anything as simple as a blog or as complex as a dissertation or monograph in Typst, Rheo enables you to publish it in multiple formats. If you are willing to learn a little bit of syntax, you can turn a piece of writing into a website, an adaptive document, and/or a printable document.

-

Some of the things you can write and publish with Rheo include:

-
    -
  • A blog
  • -
  • A paper
  • -
  • A dissertation
  • -
  • A book manuscript
  • -
  • A novel
  • -
  • A textbook
  • -
  • Technical documentation
  • -
-

Rheo is for anyone who has ever spent regrettable hours formatting citatons, fighting with LaTeX, who has experienced the limitations of Markdown, or who wants to benefit from the richer writing experience that Typst makes possible (more on this in the next section). It is for students and teachers, humanists and scientists, bloggers and novelists.

-

If you have only ever used Microsoft Word to author text, or haven’t heard the phrase ‘markup language’ before, we recommend first familiarizing yourself with Typst via the excellent tutorial. This should give you a good intuition for what Typst is—a markup language similar to but also more powerful than Markdown—and why you might want to use Rheo to typeset your documents.

-
- - - - - - \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/relative-linking.html b/tests/ref/examples/rheo_docs/html/relative-linking.html deleted file mode 100644 index 6f48870..0000000 --- a/tests/ref/examples/rheo_docs/html/relative-linking.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - Relative linking - - -
- -

Rheo

-
- -
-

Rheo allows you to write documents in plain Typst without requiring any additional syntax or metadata. Because Rheo can combine multiple files into unified outputs, however, we need a way to reference other files in the same Rheo project.

-

The syntax for these relative links in Rheo should be familiar, as they look just like regular Typst links, but reference a .typ file in the same directory as its target:

-
#link("./another-section.typ")[Another section]
-

When you compile a project with Rheo, relative links to other Typst documents in the same directory will be resolved and transformed according to the output format. What a relative link transforms to depends on both the output format and your Rheo configuration, as using features such as spines affects the control flow between your source Typst and output formats.

-
    -
  • In HTML, relative links become <a> tags that point to the relevant html page.
  • -
  • In PDF, relative links either become plain text (if input Typst is not combined, and thus produces one PDF per source document), or links to the relevant sections in the output document (if your config specifies a spine with the merge attribute set).
  • -
  • In EPUB, relative links become links to the relevant sections in the EPUB.
  • -
-

Relative linking is what allows Rheo to produce fully functional static sites. It is also a feature that you can use to help you organize large writing projects. (Note that the Typst import keyword works as you would expect in Rheo, and so can also/still be used as a mechanism to modularize projects.)

-
- - - - - - \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/rheotoml.html b/tests/ref/examples/rheo_docs/html/rheotoml.html deleted file mode 100644 index 16f987b..0000000 --- a/tests/ref/examples/rheo_docs/html/rheotoml.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - Rheo.toml - - -
- -

Rheo

-
- -
-

Rheo is a CLI that produces PDF, HTML, and EPUB simultaneously from a directory of Typst source documents. The directory that contains your Typst is called the project directory, and you can compile it like so:

-
rheo compile path/to/projectdirectory
-

In general, there are two ways to configure Rheo:

-
    -
  1. By passing flags directly to the CLI command.
  2. -
  3. By specifying configuration in a rheo.toml file at the root of the project directory.
  4. -
-

If you compile a Rheo project directory without a rheo.toml file, the following default settings will be applied to compile your project.

-
version = "0.1.0"
content_dir = "./"
build_dir = "build"
formats = ["pdf", "html", "epub"]

[epub.spine]
vertebrae = ["**/*.typ"]
title = "[project directory name]"
-

To point Rheo to a rheo.toml file that is not at the root of the project directory, specify it directly via the CLI:

-
rheo compile path/to/project --config path/to/config 
-
- - - - - - \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/spines.html b/tests/ref/examples/rheo_docs/html/spines.html deleted file mode 100644 index dcca598..0000000 --- a/tests/ref/examples/rheo_docs/html/spines.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - Spines - - -
- -

Rheo

-
- -
-

Spines

-

A spine in Rheo is the backbone or ‘table of contents’ of Typst source files that should be compiled to an output format. It takes its name from the epub specification, in which the spine articulates—or reticulates— the set and order of chapters included.

-

You can specify a spine’s vertebrae for any output format using an array of glob strings in rheo.toml:

-
[epub.spine]
title = "My epub"
vertebrae = ["intro.typ", "*.typ"]
-

Notice how the first entry intro.typ is a specific file, whereas the second *.typ captures a range of files. When a glob string captures a range of source files, they will be ordered lexicographically in the spine.

-

EPUB

-

An EPUB must have a spine in order to be valid. By default, Rheo will infer the following spine if not specified:

-
[epub.spine]
title = "[project folder name]"
vertebrae = ["**/*.typ"]
-

PDF

-

By default, Rheo generates one PDF per Typst source file. You can specify a spine for the PDF format in order to reticulate multiple source documents into a single output PDF by indicating the vertebrae and setting merge to true:

-
[pdf.spine]
title = "My reticulated pdf"
vertebrae = ["intro.typ", "*.typ"]
merge = true
-

In a PDF generated in this way, relative links will resolve to internal document links that point to the relevant section.

-

HTML

-

Rheo does not currently support customizing HTML spines. The default spine uses all Typst files:

-
[html.spine]
title = "[project folder name]"
vertebrae = ["**/*.typ"]
-
- - - - - - \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/style.metadata.json b/tests/ref/examples/rheo_docs/html/style.metadata.json deleted file mode 100644 index 3f3ec36..0000000 --- a/tests/ref/examples/rheo_docs/html/style.metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "filetype": "css", - "file_size": 10339, - "path": "style.css", - "hash": "941a9bc8b4b6f672fa89dcfa54f2426ea7a804d5c9dc4023cdfeeefe9102eb8d" -} \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/html/why-is-rheo.html b/tests/ref/examples/rheo_docs/html/why-is-rheo.html deleted file mode 100644 index 8779dab..0000000 --- a/tests/ref/examples/rheo_docs/html/why-is-rheo.html +++ /dev/null @@ -1,62 +0,0 @@ - - - - Why Rheo? - - -
- -

Rheo

-
- -
-

Why do we need Rheo?

-

Rheo (ree-oh) is an open source typesetting and static site engine for Typst. It is a typesetting engine because it produces typeset digital documents such as PDF and EPUB, and a static site engine because it produces websites that don’t require communication with a custom backend server, but rather are self-sufficient sets of files that can be natively opened a browser (static sites). Most static site engines these days employ Markdown, a markup format that is approachable and pretty generic, allowing folks who are not familiar with or otherwise don’t want to deal directly with the required file formats of the web— HTML, CSS, and Javascript— to write blog posts and other content which can then be pumped into a static site.

-

As useful as it is, Markdown has its ambiguities. For one, there isn’t a standardized syntax for citations or footnotes. Though extensions exist that can produce these, they are not supported in the core Markdown syntax, meaning that it’s not really Markdown and can’t be relied upon to work in all contexts that support Markdown. Markdown is great when using hypertext (hyperlinks, images, etc). It’s not so great when it comes to things like tables, figures, and math.

-

Typst is a markup language that integrates with plain text, like Markdown, making it easy to adopt and joyful to write. Unlike Markdown, however, it is also a Turing-complete programming language with a modern type system, meaning that it is possible (though not necessary) to express sophisticated conditional logic controlling where and how text is rendered. Typst has a concrete and concise syntax for footnotes and citations, and can express visual constructs such as tables, figures, colors, and mathematical formulas. It was developed as a modern alternative to LaTeX, Leslie Lamport’s legendary 1980s addition to Donald Knuth’s original ‘78 Tex typesetting system. For the past 40 years, LaTeX has been the most expressive way to produce PDF documents, rendering it the de facto standard for academic and scientific publication. In the past few years, Typst has become the most promising and powerful alternative to LaTeX due to its maintainers’ effort to build out a reliable PDF compilation toolchain.

-

In 2025, Typst added experimental support for HTML compilation. Though there are still many features in Typst that will only produce meaningful output in the PDF toolchain, the HTML toolchain now supports all of the essential features for academic documents in the humanities: text decoration, headings, hyperlinks, footnotes, and citations.1 This makes it an extremely good replacement for Markdown as a markup language in a static site engine, and so: enter Rheo.

-

Rheo is a CLI (command line interface) that produces PDF, HTML, and EPUB simultaneously from a folder of Typst documents. It is a static site engine because it can produce a fully valid website: all it needs is a folder containing valid Typst. Rheo also provides mechanisms to combine multiple Typst files into a unified EPUB or PDF, making it a tool that improves the experience of writing books, dissertations, or any other long-form text in Typst. On the other side of the same coin, Rheo allows you to produce an offline version of a website such as a blog written in Typst through its PDF/EPUB toolchain.

-

Rheo allows you to compile multiple Typst files that link to each other into a single output, adding what is needed (relative linking) in order to make Typst an ideal markup language for writing static sites. Typst is the most elegant and flexible way to typeset PDF documents today; Rheo extends Typst’s capabilities, allowing you to additionally typeset EPUBs and generate static sites from the same source.2 Naturally, this blog post was written in Typst, and this site was made with Rheo. If you’re already convinced, feel free to jump ahead to Getting Started to download Rheo on your system and start writing.

-

The philosophy of Rheo

-

Rheo is a prefix or combining form in English that originates from the Greek word rheos (ῥέος), meaning flow, stream, or current. Rheo flows Typst documents into a number of concurrent output formats in PDF, HTML, and EPUB. But other meanings lurk beneath the surface of this basic idea. Sarah Pourciau has argued that the oceanic is a deep-rooted metaphor in computing, as all computation at some level seeks solid space in a sea of digital noise (Pourciau 2022). From Alan Turing’s partial solution to David Hilbert’s Entscheidungsproblem in the universal machine, to Claude Shannon’s information theory, to Leslie Lamport’s ordering of events in a distributed system, the key issue at hand is how to carve out clarity from uncertainty and confusion. Writing has played a magisterial role in calming the storm of imprecise thought. Long before computation arrived on the scene, the written word has served as the steward of reason, in the Western world and beyond, from Mesopotamian cunieform to Twitter. Nota bene (‘Take note’): that writing can also herald chaos and confusion doesn’t invalidate its capacity for spreading sensibility.

-

Rheo is a tool that facilitates the production and publication of documents following from the original vision of the Internet as a mechanism for lively and reasonably unfettered academic exchange, rather than the densely commercial space of platform capitalism that it has become. It should not be so difficult, given the extraordinary capacities of software and hardware today, to make a piece of writing publically available in a plain and pleasant format. That there exist digital humanities initiatives measured in months and years to bring books to the web as basic websites is a clear sign that something has gone awry.3

-

Rheo aims to enable the publication of more books, blog posts, and papers without the necessary capitalist ceremony of creating an account on Substack, Medium, or Squarespace. A website without any interactive elements such as forms, online marketplaces, or comments should be simple to set up, as it isn’t rocket science in 2025 thanks to all the hard work that folks have put into Internet protocols and web standards. It should be simple to create a PDF or EPUB for sharing with colleagues or collaborators—as simple as it is to send an email.

-

This is the vision of the world to which we at the free computing lab aspire, and in search of which we have built Rheo. Rheo is the first installment in a larger set of writing tools we aim to build, which will include processes for collaboratively drafting documents, constructing and working with digital libraries, and more.

-

Bibliography

-
-
    -
  • Pourciau, Sarah. 2022. “On the Digital Ocean.” Critical Inquiry 48 (2): 233–61. https://doi.org/10.1086/717319.
  • -
-
-

Footnotes

-
- - - -
-
    -
  1. 1 I qualify this with ‘in the humanities’ as scientific papers often require tables, figures, and mathematical markup. These features are on Typst’s roadmap for html, but are not yet available at time of writing (January 2026).
  2. -
  3. 2EPUB is on Typst’s roadmap, but is not yet natively supported.
  4. -
  5. 3 There are many exciting and experimental ways of presenting text and other conent in the digital humanities. But we think that it should be easier that it currently is to publish and distribute books digitally, simply and straightforwardly.
  6. -
-
- - - \ No newline at end of file diff --git a/tests/ref/examples/rheo_docs/pdf/rheo_docs.metadata.json b/tests/ref/examples/rheo_docs/pdf/rheo_docs.metadata.json deleted file mode 100644 index 2827702..0000000 --- a/tests/ref/examples/rheo_docs/pdf/rheo_docs.metadata.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "filetype": "pdf", - "file_size": 101727, - "page_count": 5 -} \ No newline at end of file From 0358497e39f276fe042d35624d314cf2bccbb7da Mon Sep 17 00:00:00 2001 From: Lachlan Kermode Date: Wed, 11 Feb 2026 14:46:31 +0100 Subject: [PATCH 4/4] Doesn't bump version yet --- CLAUDE.md | 1 + examples/init_template/rheo.toml | 22 ---------------------- src/templates/init/rheo.toml | 2 +- 3 files changed, 2 insertions(+), 23 deletions(-) delete mode 100644 examples/init_template/rheo.toml diff --git a/CLAUDE.md b/CLAUDE.md index 98d3abf..6837452 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -759,6 +759,7 @@ Then use `mcp__beads__*` functions instead of CLI commands. - ❌ Do NOT create markdown TODO lists - ❌ Do NOT use external issue trackers - ❌ Do NOT duplicate tracking systems +- ❌ Do NOT run `bd sync` — beads is local-only in this project, there is nothing to sync --- diff --git a/examples/init_template/rheo.toml b/examples/init_template/rheo.toml deleted file mode 100644 index 0f513cc..0000000 --- a/examples/init_template/rheo.toml +++ /dev/null @@ -1,22 +0,0 @@ -version = "0.1.1" -content_dir = "content" - -[pdf.spine] -title = "rheo_project" -vertebrae = ["index.typ"] -merge = true - -[epub.spine] -title = "rheo_project" -vertebrae = ["index.typ", "about.typ"] -version = "0.1.2" -content_dir = "content" - -[pdf.spine] -title = "rheo_project" -vertebrae = ["index.typ"] -merge = true - -[epub.spine] -title = "rheo_project" -vertebrae = ["index.typ", "about.typ"] diff --git a/src/templates/init/rheo.toml b/src/templates/init/rheo.toml index 41233c7..a213c61 100644 --- a/src/templates/init/rheo.toml +++ b/src/templates/init/rheo.toml @@ -1,4 +1,4 @@ -version = "0.1.2" +version = "0.1.1" content_dir = "content" [pdf.spine]