review classifier: plain table cells, no backslash escapes
This commit is contained in:
parent
a9d181b53f
commit
a2dca32bb8
3 changed files with 57 additions and 18 deletions
|
|
@ -842,26 +842,37 @@ fn overall_line(overall: Overall) -> &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
/// `text` as one table cell's inline text: on one line, with every character
|
||||
/// that could end the cell, start markup, math (`$`) or raw HTML escaped, and a zero-width
|
||||
/// space after every `@`, `#`, `!`, `://` and `www.`, so it carries no live
|
||||
/// mention, issue or PR reference, or link. The forge links issue and PR
|
||||
/// numbers and bare URLs itself, so the escapes alone don't stop those.
|
||||
/// `text` as one table cell's inline text: on one line, with a backslash before
|
||||
/// every character that could end the cell, start markup, math (`$`) or raw
|
||||
/// HTML, and a zero-width space after every `@`, `#`, `!`, `://` and `www.`, so
|
||||
/// it carries no live mention, issue or PR reference, or link. The forge links
|
||||
/// issue and PR numbers and bare URLs itself, so the escapes alone don't stop
|
||||
/// those; `#` and `!` get only the zero-width space.
|
||||
///
|
||||
/// `_` is escaped except between two alphanumerics, where it can't open
|
||||
/// emphasis (`ci_metrics.rs`). Other punctuation, such as `(`, `)`, `.` and
|
||||
/// `:`, passes through: it starts no markup inside a table cell, and the `[`
|
||||
/// that would make `(` a link target is escaped.
|
||||
fn cell(text: &str) -> String {
|
||||
let mut out = String::with_capacity(text.len());
|
||||
for (i, word) in text.split_whitespace().enumerate() {
|
||||
if i > 0 {
|
||||
out.push(' ');
|
||||
}
|
||||
for c in word.chars() {
|
||||
let chars: Vec<char> = word.chars().collect();
|
||||
for (j, &c) in chars.iter().enumerate() {
|
||||
match c {
|
||||
'\\' | '|' | '`' | '*' | '_' | '~' | '[' | ']' | '(' | ')' | '<' | '>' | '&'
|
||||
| '$' => {
|
||||
'_' if j > 0
|
||||
&& chars[j - 1].is_alphanumeric()
|
||||
&& chars.get(j + 1).is_some_and(|n| n.is_alphanumeric()) =>
|
||||
{
|
||||
out.push(c);
|
||||
}
|
||||
'\\' | '|' | '`' | '*' | '_' | '~' | '[' | ']' | '<' | '>' | '&' | '$' => {
|
||||
out.push('\\');
|
||||
out.push(c);
|
||||
}
|
||||
'#' | '!' => {
|
||||
out.push('\\');
|
||||
out.push(c);
|
||||
out.push('\u{200b}');
|
||||
}
|
||||
|
|
@ -1932,7 +1943,7 @@ mod tests {
|
|||
.count();
|
||||
assert_eq!(unescaped, 5, "{line}");
|
||||
assert!(
|
||||
line.contains("\\!\u{200b}\\[\\]") && line.contains("\\<b\\>"),
|
||||
line.contains("!\u{200b}\\[\\]") && line.contains("\\<b\\>"),
|
||||
"{line}"
|
||||
);
|
||||
}
|
||||
|
|
@ -1965,8 +1976,33 @@ mod tests {
|
|||
let text = cell("see https://evil.example/x, WWW.evil.example, #1, o/r#3 and !4");
|
||||
assert_eq!(
|
||||
text,
|
||||
"see https://\u{200b}evil.example/x, WWW.\u{200b}evil.example, \\#\u{200b}1, \
|
||||
o/r\\#\u{200b}3 and \\!\u{200b}4"
|
||||
"see https://\u{200b}evil.example/x, WWW.\u{200b}evil.example, #\u{200b}1, \
|
||||
o/r#\u{200b}3 and !\u{200b}4"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_plain_reason_reads_without_backslashes() {
|
||||
assert_eq!(
|
||||
cell("an added #[allow(clippy::foo)] in ci_metrics.rs (see main_loop_v2.rs)"),
|
||||
"an added #\u{200b}\\[allow(clippy::foo)\\] in ci_metrics.rs (see main_loop_v2.rs)"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_underscore_escapes_unless_it_sits_between_alphanumerics() {
|
||||
// Presence control: the edge underscores are escaped.
|
||||
assert_eq!(
|
||||
cell("_em_ __b__ a_ _b a__b snake_case"),
|
||||
"\\_em\\_ \\_\\_b\\_\\_ a\\_ \\_b a\\_\\_b snake_case"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_reason_with_markup_characters_keeps_them_inert() {
|
||||
assert_eq!(
|
||||
cell(r"a\b `c` *d* ~e~ [f] <g> &h; i|j $k"),
|
||||
r"a\\b \`c\` \*d\* \~e\~ \[f\] \<g\> \&h; i\|j \$k"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue