Compare commits

...
4 changed files with 23 additions and 3 deletions
+2
View File
File diff suppressed because one or more lines are too long
+7 -3
View File
@@ -276,6 +276,9 @@ fn tokenize(s: &str, base: &Fmt, depth: usize, refs: &Refs) -> Vec<Node> {
// text. A scan pays for what it reads; earlier bracket matches are looked up in `known`.
let ticks = Backticks::new(s);
let mut links = LinkScan { text: s, refs, ticks: &ticks, known: HashMap::new(), budget: s.len().saturating_mul(8).saturating_add(8192) };
// Where the last comment end is: a comment opener after it has none to find, so a run of
// unclosed `<!--` doesn't search the rest of the text once each.
let last_comment_end = s.rfind("-->");
let b = s.as_bytes();
let mut i = 0usize;
let mut text_start = 0usize;
@@ -366,7 +369,7 @@ fn tokenize(s: &str, base: &Fmt, depth: usize, refs: &Refs) -> Vec<Node> {
}
}
b'<' => {
if let Some((end, parsed)) = angle_inlines(s, i, base) {
if let Some((end, parsed)) = angle_inlines(s, i, base, last_comment_end) {
flush!();
nodes.extend(parsed);
i = end;
@@ -394,8 +397,9 @@ fn tokenize(s: &str, base: &Fmt, depth: usize, refs: &Refs) -> Vec<Node> {
nodes
}
fn angle_inlines(s: &str, start: usize, base: &Fmt) -> Option<(usize, Vec<Node>)> {
if let Some(pos) = s.get(start..).and_then(|rest| rest.strip_prefix("<!--")).and_then(|rest| rest.find("-->")) {
fn angle_inlines(s: &str, start: usize, base: &Fmt, last_comment_end: Option<usize>) -> Option<(usize, Vec<Node>)> {
let closable = last_comment_end.is_some_and(|e| e >= start + 4);
if let Some(pos) = s.get(start..).and_then(|rest| rest.strip_prefix("<!--")).filter(|_| closable).and_then(|rest| rest.find("-->")) {
return Some((start + 4 + pos + 3, Vec::new()));
}
let rest = s.get(start + 1..).unwrap_or("");
+13
View File
@@ -714,3 +714,16 @@ fn exported_link_destinations_read_back_unchanged() {
assert_eq!(md("https://example.com/a b"), "[x](<https://example.com/a b>)");
assert_eq!(md("https://e.com/x\ny"), "[x](https://e.com/xy)");
}
#[test]
fn unclosed_inline_comments_are_text_without_a_search_each() {
// #3714-style: each unclosed `<!--` searched the rest of the paragraph for `-->`.
let src = "<!--".repeat(200_000);
let t = std::time::Instant::now();
let text: String = inl(&src).into_iter().filter_map(|i| if let Inline::Text(t, _) = i { Some(t) } else { None }).collect();
assert_eq!(text, src);
assert!(t.elapsed() < std::time::Duration::from_secs(10), "{:?}", t.elapsed());
// A comment that does close still goes, after an unclosed one too.
let text: String = inl("a <!-- b --> c <!-- d").into_iter().filter_map(|i| if let Inline::Text(t, _) = i { Some(t) } else { None }).collect();
assert_eq!(text, "a c <!-- d");
}
+1
View File
File diff suppressed because one or more lines are too long