gatewayd: links: url_len and closes as their comments say

M5b review, findings 1 and 2. url_len ended a clean reply's URL at any
`<` outside parentheses, not at a `<` before white space, a bracket,
`<`, `>` or the end; closes used a count of characters as a byte
offset, so a closer indented with a no-break space did not close its
fence. Both bodies, and fence_end's (an index replaced by `get`), are
the reference's again. tests/links_review.rs pins both cases with the
reference's output.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-27 19:08:42 -07:00
co-authored by Claude Opus 5.5
parent 27a6354a80
commit 27aeab48e1
3 changed files with 55 additions and 50 deletions
+29
View File
@@ -0,0 +1,29 @@
//! Two cases the M5b review found where `links::disarm` did not follow the comments of its
//! helpers: a `<` inside a clean reply's URL, and a fence closed by a line indented with a no-break
//! space (M5b review, implementer log). Each expected text is the reference's.
use gatewayd::links::disarm;
#[test]
fn a_url_runs_on_past_a_less_than_sign_that_starts_no_autolink() {
// `url_len`: only a `<` before white space, a bracket, `<`, `>` or the end stops the URL of a
// clean reply, so the image after it is wrapped with the URL, whole.
let text = "see https://a.example/x<![i](https://e.example/d) now";
assert_eq!(
disarm(text, false).text,
"see `https://a.example/x<![i](https://e.example/d)` now"
);
assert_eq!(
disarm(text, true).text,
"see `https://a.example/x`< `![i](https://e.example/d)` now"
);
}
#[test]
fn a_closer_indented_with_a_no_break_space_closes_the_fence() {
// `closes`: up to three spaces or no-break spaces before the closing run, counted in
// characters; the no-break space is two bytes.
let text = "```\n![i](https://e.example/d)\n\u{a0}```\nafter";
assert_eq!(disarm(text, false).text, text);
assert_eq!(disarm(text, true).text, text);
}