Skip to content

rustdoc: Don't add "Read more" link if there is no extra content #105780

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions src/librustdoc/html/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -567,11 +567,12 @@ struct SummaryLine<'a, I: Iterator<Item = Event<'a>>> {
inner: I,
started: bool,
depth: u32,
skipped_tags: u32,
}

impl<'a, I: Iterator<Item = Event<'a>>> 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 }
}
}

Expand Down Expand Up @@ -601,13 +602,15 @@ impl<'a, I: Iterator<Item = Event<'a>>> 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;
check_if_allowed_tag(c)
}
Event::End(ref c) => {
if is_forbidden_tag(c) {
self.skipped_tags += 1;
return None;
}
self.depth -= 1;
Expand All @@ -616,6 +619,9 @@ impl<'a, I: Iterator<Item = Event<'a>>> 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))
Expand Down Expand Up @@ -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<'_>| {
Expand All @@ -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
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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#" <a{}>Read more</a>"#, assoc_href_attr(item, link, cx));

if let Some(idx) = summary_html.rfind("</p>") {
Expand Down
34 changes: 34 additions & 0 deletions src/test/rustdoc/read-more-unneeded.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Regression test for https://github.com/rust-lang/rust/issues/105677.
// This test ensures that the "Read more" link is only generated when
// there is actually more documentation to read after the short summary.

#![crate_name = "foo"]

pub trait MyFrom {
/// # Hello
/// ## Yolo
/// more!
fn try_from1();
/// a
/// b
/// c
fn try_from2();
/// a
///
/// b
///
/// c
fn try_from3();
}

pub struct NonZero;

// @has 'foo/struct.NonZero.html'
impl MyFrom for NonZero {
// @matches - '//*[@class="docblock"]' '^Hello Read more$'
fn try_from1() {}
// @matches - '//*[@class="docblock"]' '^a\sb\sc$'
fn try_from2() {}
// @matches - '//*[@class="docblock"]' '^a Read more$'
fn try_from3() {}
}
2 changes: 0 additions & 2 deletions src/test/rustdoc/trait-impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ impl Trait for Struct {
// @has - '//*[@id="method.b"]/../../div[@class="docblock"]' 'These docs contain'
// @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a' 'reference link'
// @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a/@href' 'https://example.com'
// @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a' 'Read more'
// @has - '//*[@id="method.b"]/../../div[@class="docblock"]/a/@href' 'trait.Trait.html#tymethod.b'
fn b() {}

// @!has - '//*[@id="method.c"]/../../div[@class="docblock"]' 'code block'
Expand Down