From c0d79f4c42ad85c5b983dad6d38e16801015da39 Mon Sep 17 00:00:00 2001 From: benmandrew Date: Wed, 21 Oct 2026 00:07:16 +0100 Subject: [PATCH] feat: add --no-preamble to omit the markup definitions The output always defines diff-added and diff-deleted, so a caller that wants its own styling has to strip them from every file. With --no-preamble they are left out, and the caller imports its own definitions. render() is unchanged; render_body() returns the body. --- README.md | 3 ++- src/main.rs | 10 +++++++++- src/render.rs | 8 ++++++-- tests/integration.rs | 14 +++++++++++++- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0e7ee93..1f433c4 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ cargo install --git https://github.com/sou1118/typdiff ## Usage ``` -typdiff [-o ] +typdiff [-o ] [--no-preamble] ``` | Argument | Description | @@ -98,6 +98,7 @@ typdiff [-o ] | `` | Path to the old Typst file | | `` | Path to the new Typst file | | `-o, --output ` | Output file path (defaults to stdout) | +| `--no-preamble` | Omit the definitions of `diff-added` and `diff-deleted`, so the output can import its own | ### Examples diff --git a/src/main.rs b/src/main.rs index c573d4f..d35f278 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,10 @@ struct Cli { /// Output file path (defaults to stdout) #[arg(short, long)] output: Option, + + /// Omit the definitions of diff-added and diff-deleted from the output + #[arg(long)] + no_preamble: bool, } fn main() -> Result<()> { @@ -39,7 +43,11 @@ fn main() -> Result<()> { let diff_results = typdiff::diff::diff(&old_blocks, &new_blocks); - let output = typdiff::render::render(&diff_results); + let output = if cli.no_preamble { + typdiff::render::render_body(&diff_results) + } else { + typdiff::render::render(&diff_results) + }; match cli.output { Some(path) => { diff --git a/src/render.rs b/src/render.rs index 37a775a..59a0d9f 100644 --- a/src/render.rs +++ b/src/render.rs @@ -14,9 +14,13 @@ const PREAMBLE: &str = r##"#let diff-added(body) = { /// Render a list of diff results into a compilable Typst source string. pub fn render(results: &[DiffResult]) -> String { + format!("{PREAMBLE}\n{}", render_body(results)) +} + +/// Render diff results without the preamble that defines `diff-added` and +/// `diff-deleted`. The caller must make those functions available. +pub fn render_body(results: &[DiffResult]) -> String { let mut out = String::new(); - out.push_str(PREAMBLE); - out.push('\n'); for result in results { match result { diff --git a/tests/integration.rs b/tests/integration.rs index dacad43..403994a 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1,6 +1,6 @@ use typdiff::diff::diff; use typdiff::parse::parse; -use typdiff::render::render; +use typdiff::render::{render, render_body}; fn run_diff(old: &str, new: &str) -> String { let old_blocks: Vec<_> = parse(old) @@ -209,3 +209,15 @@ fn test_indented_line_comment_does_not_split_paragraph() { // A whitespace-only line would be treated as a paragraph break by Typst. assert!(!output.contains("\n \n")); } + +#[test] +fn test_render_body_omits_preamble() { + let old_blocks = parse("Old text.\n"); + let new_blocks = parse("New text.\n"); + let output = render_body(&diff(&old_blocks, &new_blocks)); + + // The caller imports its own definitions, which a preamble would shadow. + assert!(!output.contains("#let diff-added")); + assert!(!output.contains("#let diff-deleted")); + assert!(output.contains("#diff-added[New]")); +}