From d165aceef53af665cadd06e6398a35cadbb37fe6 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Tue, 15 Sep 2026 12:58:23 -0500 Subject: [PATCH 1/2] fix(latex): leftover tcbstartdraftmode and tcbstopdraftmode tcolorbox leftover \tcbstartdraftmode / \tcbstopdraftmode stay one Structure command so following flush prose does not join. --- src/sentence/unicode.rs | 4 ++++ tests/latex_leftover_cmds.rs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/sentence/unicode.rs b/src/sentence/unicode.rs index d50a9fc..6d7d0cf 100644 --- a/src/sentence/unicode.rs +++ b/src/sentence/unicode.rs @@ -1571,6 +1571,8 @@ pub(crate) fn leftover_keyval_cs_name(tail: &str) -> Option<&'static str> { "tcbifexternal", "tcbcontinuedraftmode", "tcbinterruptdraftmode", + "tcbstartdraftmode", + "tcbstopdraftmode", "tcbposterset", "tcbfontsize", "tcbEXTERNALIZE", @@ -1767,6 +1769,8 @@ fn leftover_keyval_kind(name: &str) -> VerbKind { | "sarg" | "tcbcontinuedraftmode" | "tcbinterruptdraftmode" + | "tcbstartdraftmode" + | "tcbstopdraftmode" | "PyLTVerbatimEnv" => VerbKind::Listingcont, "setmintedinline" | "usemintedstyle" diff --git a/tests/latex_leftover_cmds.rs b/tests/latex_leftover_cmds.rs index 503db4c..5a4cf11 100644 --- a/tests/latex_leftover_cmds.rs +++ b/tests/latex_leftover_cmds.rs @@ -378,6 +378,8 @@ fn leftover_constructors_do_not_join() { leftover_cmd_stays_atomic(r"\tcbposterset{colback=red}"); leftover_cmd_stays_atomic(r"\tcbcontinuedraftmode"); leftover_cmd_stays_atomic(r"\tcbinterruptdraftmode"); + leftover_cmd_stays_atomic(r"\tcbstartdraftmode"); + leftover_cmd_stays_atomic(r"\tcbstopdraftmode"); leftover_cmd_stays_atomic(r"\tcbfontsize{2}"); leftover_cmd_stays_atomic(r"\tcbindex"); leftover_cmd_stays_atomic(r"\tcbEXTERNALIZE"); @@ -410,6 +412,8 @@ fn leftover_constructors_do_not_join() { extras_skip_no_brace("cs"); extras_skip_no_brace("OptionalLocalPitonStyle"); extras_skip_no_brace("tcbposterset"); + extras_skip_no_brace("tcbstartdraftmode"); + extras_skip_no_brace("tcbstopdraftmode"); extras_skip_no_brace("tcbfontsize"); extras_skip_no_brace("tcbset"); extras_skip_no_brace("tcbuselibrary"); From 8712a4c0a0e12ef6596fb39ec606e425b38016ea Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Tue, 15 Sep 2026 13:13:58 -0500 Subject: [PATCH 2/2] fix: leftover .`` plaintext SemBr cycle After protect_inline_tokens, UAX can split `.`` ` into `.` plus a leftover backtick. Do not invent a space there or format_text cycles `.`` ` vs `. `` `. --- src/sentence/unicode.rs | 15 ++++++++++++++- tests/sentence_delim_props.rs | 12 ++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/sentence/unicode.rs b/src/sentence/unicode.rs index 6d7d0cf..5a785f2 100644 --- a/src/sentence/unicode.rs +++ b/src/sentence/unicode.rs @@ -3230,7 +3230,11 @@ fn push_segment_preserving_space(dest: &mut String, piece: &str) { }) // `!!a` is one UAX fragment; inventing `!! a` then splitting // `!! a` on the next pass is a wrap/SemBr cycle. - && !dest.ends_with("!!"); + && !dest.ends_with("!!") + // After protect_inline_tokens, `.`` ` is `.` + leftover backtick + // (`dest="…."`, `piece="`\\0PHn\\0"`). Inventing `. `` ` then + // wrapping back is a SemBr cycle (ubuntu CI seed). + && !(dest.ends_with(['.', '!', '?']) && piece.starts_with('`')); if need_space { dest.push(' '); } @@ -3711,6 +3715,15 @@ mod tests { UnicodeSentenceSplitter::new().split(text) } + #[test] + fn period_then_latex_quotes_does_not_invent_space() { + assert_eq!( + split("^{`}`.`` A0`"), + vec!["^{`}`.`` A0`".to_string()], + "must not invent space between . and ``" + ); + } + #[test] fn single_quote_bang_capital_stays_one_sentence() { assert_eq!( diff --git a/tests/sentence_delim_props.rs b/tests/sentence_delim_props.rs index 3a1e5c1..6b472e2 100644 --- a/tests/sentence_delim_props.rs +++ b/tests/sentence_delim_props.rs @@ -76,6 +76,18 @@ fn plaintext_latex_quoted_bang_letter_is_span_safe() { } #[test] +#[test] +fn plaintext_period_then_latex_quotes_is_idempotent() { + // ubuntu CI seed: first pass keeps `.`` `; second pass invents `. `` `. + let input = ".^{`}`.`` A0`"; + let out = format_plain(input); + assert_eq!( + format_plain(&out), + out, + "idempotence\n in={input:?}\n out={out:?}" + ); +} + fn plaintext_quoted_bang_letter_is_span_safe() { let input = "\"!!a\""; let out = format_plain(input);