Skip to content

Commit d73b841

Browse files
authored
Unrolled build for rust-lang#117662
Rollup merge of rust-lang#117662 - GuillaumeGomez:links-in-headings, r=notriddle [rustdoc] Allows links in headings Reopening of rust-lang#94360. # Explanations Rustdoc currently doesn't follow the markdown spec on headings: we don't allow links in them. So instead of having headings linking to themselves, this PR generates an anchor on the left side like this: ![image](https://github.com/rust-lang/rust/assets/3050060/a118a7e9-5ef8-4d07-914f-46defc3245c3) <details> <summary>previous version</summary> ![image](https://github.com/rust-lang/rust/assets/3050060/c34fa844-9cd4-47dc-bb51-b37f5f66afee) </details> Having the anchor always displayed allows for mobile devices users to be able to have a link to the anchor. The different color used for the anchor itself is the same as links so people notice when looking at it that they can click on it. You can test it [here](https://rustdoc.crud.net/imperio/links-in-headings/std/index.html). cc `@camelid` r? `@notriddle`
2 parents 0547c41 + bf4a20c commit d73b841

12 files changed

+211
-99
lines changed

src/librustdoc/html/markdown.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,6 @@ impl<'a, 'b, 'ids, I: Iterator<Item = SpannedEvent<'a>>> Iterator
530530
for event in &mut self.inner {
531531
match &event.0 {
532532
Event::End(Tag::Heading(..)) => break,
533-
Event::Start(Tag::Link(_, _, _)) | Event::End(Tag::Link(..)) => {}
534533
Event::Text(text) | Event::Code(text) => {
535534
id.extend(text.chars().filter_map(slugify));
536535
self.buf.push_back(event);
@@ -549,12 +548,10 @@ impl<'a, 'b, 'ids, I: Iterator<Item = SpannedEvent<'a>>> Iterator
549548

550549
let level =
551550
std::cmp::min(level as u32 + (self.heading_offset as u32), MAX_HEADER_LEVEL);
552-
self.buf.push_back((Event::Html(format!("</a></h{level}>").into()), 0..0));
551+
self.buf.push_back((Event::Html(format!("</h{level}>").into()), 0..0));
553552

554-
let start_tags = format!(
555-
"<h{level} id=\"{id}\">\
556-
<a href=\"#{id}\">",
557-
);
553+
let start_tags =
554+
format!("<h{level} id=\"{id}\"><a class=\"doc-anchor\" href=\"#{id}\">§</a>");
558555
return Some((Event::Html(start_tags.into()), 0..0));
559556
}
560557
event

src/librustdoc/html/markdown/tests.rs

+48-12
Original file line numberDiff line numberDiff line change
@@ -311,26 +311,38 @@ fn test_header() {
311311
assert_eq!(output, expect, "original: {}", input);
312312
}
313313

314-
t("# Foo bar", "<h2 id=\"foo-bar\"><a href=\"#foo-bar\">Foo bar</a></h2>");
314+
t(
315+
"# Foo bar",
316+
"<h2 id=\"foo-bar\"><a class=\"doc-anchor\" href=\"#foo-bar\">§</a>Foo bar</h2>",
317+
);
315318
t(
316319
"## Foo-bar_baz qux",
317320
"<h3 id=\"foo-bar_baz-qux\">\
318-
<a href=\"#foo-bar_baz-qux\">Foo-bar_baz qux</a></h3>",
321+
<a class=\"doc-anchor\" href=\"#foo-bar_baz-qux\">§</a>\
322+
Foo-bar_baz qux\
323+
</h3>",
319324
);
320325
t(
321326
"### **Foo** *bar* baz!?!& -_qux_-%",
322327
"<h4 id=\"foo-bar-baz--qux-\">\
323-
<a href=\"#foo-bar-baz--qux-\"><strong>Foo</strong> \
324-
<em>bar</em> baz!?!&amp; -<em>qux</em>-%</a>\
328+
<a class=\"doc-anchor\" href=\"#foo-bar-baz--qux-\">§</a>\
329+
<strong>Foo</strong> <em>bar</em> baz!?!&amp; -<em>qux</em>-%\
325330
</h4>",
326331
);
327332
t(
328333
"#### **Foo?** & \\*bar?!* _`baz`_ ❤ #qux",
329334
"<h5 id=\"foo--bar--baz--qux\">\
330-
<a href=\"#foo--bar--baz--qux\"><strong>Foo?</strong> &amp; *bar?!* \
331-
<em><code>baz</code></em> ❤ #qux</a>\
335+
<a class=\"doc-anchor\" href=\"#foo--bar--baz--qux\">§</a>\
336+
<strong>Foo?</strong> &amp; *bar?!* <em><code>baz</code></em> ❤ #qux\
332337
</h5>",
333338
);
339+
t(
340+
"# Foo [bar](https://hello.yo)",
341+
"<h2 id=\"foo-bar\">\
342+
<a class=\"doc-anchor\" href=\"#foo-bar\">§</a>\
343+
Foo <a href=\"https://hello.yo\">bar</a>\
344+
</h2>",
345+
);
334346
}
335347

336348
#[test]
@@ -351,12 +363,36 @@ fn test_header_ids_multiple_blocks() {
351363
assert_eq!(output, expect, "original: {}", input);
352364
}
353365

354-
t(&mut map, "# Example", "<h2 id=\"example\"><a href=\"#example\">Example</a></h2>");
355-
t(&mut map, "# Panics", "<h2 id=\"panics\"><a href=\"#panics\">Panics</a></h2>");
356-
t(&mut map, "# Example", "<h2 id=\"example-1\"><a href=\"#example-1\">Example</a></h2>");
357-
t(&mut map, "# Search", "<h2 id=\"search-1\"><a href=\"#search-1\">Search</a></h2>");
358-
t(&mut map, "# Example", "<h2 id=\"example-2\"><a href=\"#example-2\">Example</a></h2>");
359-
t(&mut map, "# Panics", "<h2 id=\"panics-1\"><a href=\"#panics-1\">Panics</a></h2>");
366+
t(
367+
&mut map,
368+
"# Example",
369+
"<h2 id=\"example\"><a class=\"doc-anchor\" href=\"#example\">§</a>Example</h2>",
370+
);
371+
t(
372+
&mut map,
373+
"# Panics",
374+
"<h2 id=\"panics\"><a class=\"doc-anchor\" href=\"#panics\">§</a>Panics</h2>",
375+
);
376+
t(
377+
&mut map,
378+
"# Example",
379+
"<h2 id=\"example-1\"><a class=\"doc-anchor\" href=\"#example-1\">§</a>Example</h2>",
380+
);
381+
t(
382+
&mut map,
383+
"# Search",
384+
"<h2 id=\"search-1\"><a class=\"doc-anchor\" href=\"#search-1\">§</a>Search</h2>",
385+
);
386+
t(
387+
&mut map,
388+
"# Example",
389+
"<h2 id=\"example-2\"><a class=\"doc-anchor\" href=\"#example-2\">§</a>Example</h2>",
390+
);
391+
t(
392+
&mut map,
393+
"# Panics",
394+
"<h2 id=\"panics-1\"><a class=\"doc-anchor\" href=\"#panics-1\">§</a>Panics</h2>",
395+
);
360396
}
361397

362398
#[test]

src/librustdoc/html/render/mod.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -1207,17 +1207,31 @@ impl<'a> AssocItemLink<'a> {
12071207
}
12081208
}
12091209

1210-
fn write_impl_section_heading(mut w: impl fmt::Write, title: &str, id: &str) {
1210+
pub fn write_section_heading(
1211+
w: &mut impl fmt::Write,
1212+
title: &str,
1213+
id: &str,
1214+
extra_class: Option<&str>,
1215+
extra: impl fmt::Display,
1216+
) {
1217+
let (extra_class, whitespace) = match extra_class {
1218+
Some(extra) => (extra, " "),
1219+
None => ("", ""),
1220+
};
12111221
write!(
12121222
w,
1213-
"<h2 id=\"{id}\" class=\"section-header\">\
1223+
"<h2 id=\"{id}\" class=\"{extra_class}{whitespace}section-header\">\
12141224
{title}\
12151225
<a href=\"#{id}\" class=\"anchor\">§</a>\
1216-
</h2>"
1226+
</h2>{extra}",
12171227
)
12181228
.unwrap();
12191229
}
12201230

1231+
fn write_impl_section_heading(w: &mut impl fmt::Write, title: &str, id: &str) {
1232+
write_section_heading(w, title, id, None, "")
1233+
}
1234+
12211235
pub(crate) fn render_all_impls(
12221236
mut w: impl Write,
12231237
cx: &mut Context<'_>,

0 commit comments

Comments
 (0)