diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index b141820fe42..aeaee524fd4 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -567,11 +567,12 @@ struct SummaryLine<'a, I: Iterator>> { inner: I, started: bool, depth: u32, + skipped_tags: u32, } impl<'a, I: Iterator>> SummaryLine<'a, I> { fn new(iter: I) -> Self { - SummaryLine { inner: iter, started: false, depth: 0 } + SummaryLine { inner: iter, started: false, depth: 0, skipped_tags: 0 } } } @@ -601,6 +602,7 @@ impl<'a, I: Iterator>> Iterator for SummaryLine<'a, I> { let is_allowed_tag = match event { Event::Start(ref c) => { if is_forbidden_tag(c) { + self.skipped_tags += 1; return None; } self.depth += 1; @@ -608,6 +610,7 @@ impl<'a, I: Iterator>> Iterator for SummaryLine<'a, I> { } Event::End(ref c) => { if is_forbidden_tag(c) { + self.skipped_tags += 1; return None; } self.depth -= 1; @@ -616,6 +619,9 @@ impl<'a, I: Iterator>> Iterator for SummaryLine<'a, I> { } _ => true, }; + if !is_allowed_tag { + self.skipped_tags += 1; + } return if !is_allowed_tag { if is_start { Some(Event::Start(Tag::Paragraph)) @@ -1096,11 +1102,11 @@ impl MarkdownItemInfo<'_> { } impl MarkdownSummaryLine<'_> { - pub(crate) fn into_string(self) -> String { + pub(crate) fn into_string_with_has_more_content(self) -> (String, bool) { let MarkdownSummaryLine(md, links) = self; // This is actually common enough to special-case if md.is_empty() { - return String::new(); + return (String::new(), false); } let mut replacer = |broken_link: BrokenLink<'_>| { @@ -1110,17 +1116,26 @@ impl MarkdownSummaryLine<'_> { .map(|link| (link.href.as_str().into(), link.new_text.as_str().into())) }; - let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer)); + let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer)) + .peekable(); + let mut summary = SummaryLine::new(p); let mut s = String::new(); - let without_paragraphs = LinkReplacer::new(SummaryLine::new(p), links).filter(|event| { + let without_paragraphs = LinkReplacer::new(&mut summary, links).filter(|event| { !matches!(event, Event::Start(Tag::Paragraph) | Event::End(Tag::Paragraph)) }); html::push_html(&mut s, without_paragraphs); - s + let has_more_content = + matches!(summary.inner.peek(), Some(Event::Start(_))) || summary.skipped_tags > 0; + + (s, has_more_content) + } + + pub(crate) fn into_string(self) -> String { + self.into_string_with_has_more_content().0 } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 80fbe9c1f06..146e5010e4e 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -467,9 +467,10 @@ fn document_short( return; } if let Some(s) = item.doc_value() { - let mut summary_html = MarkdownSummaryLine(&s, &item.links(cx)).into_string(); + let (mut summary_html, has_more_content) = + MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content(); - if s.contains('\n') { + if has_more_content { let link = format!(r#" Read more"#, assoc_href_attr(item, link, cx)); if let Some(idx) = summary_html.rfind("

") {