review classifier: escape $ in verdict cells so the forge doesn't render them as math
Forgejo's markdown renders $...$ and $$...$$ as KaTeX; a reason quoting
nix `${...}` put two $ in one cell and the span between them became a KaTeX
parse error. The cell escaper now backslash-escapes $ like its other markup.
Rule source: the math inline parser triggers on '$' and only starts a span
there (modules/markup/markdown/math/inline_parser.go, Trigger/Parse in
go-gitea/gitea, which Forgejo carries); goldmark's CommonMark backslash
escape consumes '\$' first, so the parser never sees it. Escaping each $
also covers '$$'. Backslashes are already escaped, so '\\$' stays literal.
This commit is contained in:
parent
44346d8c6c
commit
c42321ff0e
1 changed files with 26 additions and 2 deletions
|
|
@ -736,7 +736,7 @@ fn table(rows: &[Row]) -> String {
|
|||
}
|
||||
|
||||
/// `text` as one table cell's inline text: on one line, with every character
|
||||
/// that could end the cell, start markup or raw HTML escaped, and a zero-width
|
||||
/// 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.
|
||||
|
|
@ -748,7 +748,8 @@ fn cell(text: &str) -> String {
|
|||
}
|
||||
for c in word.chars() {
|
||||
match c {
|
||||
'\\' | '|' | '`' | '*' | '_' | '~' | '[' | ']' | '(' | ')' | '<' | '>' | '&' => {
|
||||
'\\' | '|' | '`' | '*' | '_' | '~' | '[' | ']' | '(' | ')' | '<' | '>' | '&'
|
||||
| '$' => {
|
||||
out.push('\\');
|
||||
out.push(c);
|
||||
}
|
||||
|
|
@ -1484,6 +1485,29 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_reason_carries_no_live_math_delimiter() {
|
||||
let mut r = row(None, true, true);
|
||||
r.reason =
|
||||
"uses https://${hyperhiveCfg.swarm.forge.domain}/metrics and $$x$$ | y".to_owned();
|
||||
let body = table(&[r]);
|
||||
let line = body.lines().nth(2).expect("a data row");
|
||||
assert!(
|
||||
line.contains("\\${hyperhiveCfg") && line.contains("\\$\\$x\\$\\$"),
|
||||
"{line}"
|
||||
);
|
||||
let bare = line
|
||||
.char_indices()
|
||||
.filter(|(i, c)| *c == '$' && (*i == 0 || line.as_bytes()[i - 1] != b'\\'))
|
||||
.count();
|
||||
assert_eq!(bare, 0, "{line}");
|
||||
let unescaped = line
|
||||
.char_indices()
|
||||
.filter(|(i, c)| *c == '|' && (*i == 0 || line.as_bytes()[i - 1] != b'\\'))
|
||||
.count();
|
||||
assert_eq!(unescaped, 8, "{line}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_reason_carries_no_link_or_reference() {
|
||||
let text = cell("see https://evil.example/x, WWW.evil.example, #1, o/r#3 and !4");
|
||||
|
|
|
|||
Loading…
Reference in a new issue