From 77b6ca0e2ac05e9acd58729549e55e137bea8e4e Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Wed, 21 Oct 2026 00:28:35 +0000 Subject: [PATCH] Keep '&' in LaTeX \href and \url addresses on import Found while testing crates/formats/src/latex.rs:2526-2545 (raw_text) Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/formats/src/latex.rs | 1 + crates/formats/src/tests.rs | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/crates/formats/src/latex.rs b/crates/formats/src/latex.rs index cc2157268..6286df477 100644 --- a/crates/formats/src/latex.rs +++ b/crates/formats/src/latex.rs @@ -2538,6 +2538,7 @@ fn raw_text(toks: &[Tok]) -> String { } }, Tok::Verb(v) | Tok::Math(v, _) => s.push_str(v), + Tok::Amp => s.push('&'), _ => {} } } diff --git a/crates/formats/src/tests.rs b/crates/formats/src/tests.rs index caad39dce..45d21d572 100644 --- a/crates/formats/src/tests.rs +++ b/crates/formats/src/tests.rs @@ -655,6 +655,29 @@ fn code_spans_and_links_around_backticks_read_as_before() { assert_eq!(p.text(), "`e a ` b then ``` and c x ] y p ` q ``f"); } +/// An unescaped `&` in a LaTeX link address is part of the address. +#[test] +fn latex_href_keeps_ampersand() { + let d = import("tex", br"\href{https://e.com/a?b=1&c=2}{link}").unwrap().unwrap(); + let links: Vec> = flat(&d) + .iter() + .filter_map(|b| if let FBlock::Para(p) = b { Some(p) } else { None }) + .flat_map(|p| p.inlines.iter()) + .filter_map(|i| if let model::Inline::Text(_, f) = i { Some(f.link.clone()) } else { None }) + .collect(); + assert_eq!(links, [Some("https://e.com/a?b=1&c=2".to_string())]); + + let d = import("tex", br"\url{https://e.com/a?b=1&c=2}").unwrap().unwrap(); + let texts: Vec<(String, Option)> = flat(&d) + .iter() + .filter_map(|b| if let FBlock::Para(p) = b { Some(p) } else { None }) + .flat_map(|p| p.inlines.iter()) + .filter_map(|i| if let model::Inline::Text(t, f) = i { Some((t.to_string(), f.link.clone())) } else { None }) + .collect(); + let url = "https://e.com/a?b=1&c=2".to_string(); + assert_eq!(texts, [(url.clone(), Some(url))]); +} + /// A `[` nothing closes, bracketed text that is not a link and links themselves used up the bracket /// scans' budget as if each had read the rest of the text: later links in the paragraph were plain /// text.