From 458e7219bc2a62f72368279945cfda632a016da1 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 22 Jul 2021 15:17:00 -0700 Subject: [PATCH] Rustdoc accessibility: use real headers for doc items This is a pretty annoying workaround: the specifications literally contradict each other on the matter of whether headers may be nested inside of summaries. We need the headers for people who use outline mode to browse rustdoc, mostly in screen readers, and the headers need to be inside the summary tag so that they're visible when the details tag is collapsed. HTML5 says it's okay, but the ordinary button semantics in ARIA say that headers nested in buttons are ignored, and summary is a button. Which means some screen readers, like NVDA, work, while others, like JAWS, don't. --- src/librustdoc/html/render/mod.rs | 20 ++++++++++---------- src/librustdoc/html/render/print_item.rs | 4 ++-- src/librustdoc/html/static/css/rustdoc.css | 17 ++++++++++++----- src/librustdoc/html/static/js/main.js | 3 ++- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 68c59612ccc44..45542b53573b5 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1350,7 +1350,7 @@ fn render_impl( ); render_rightside(w, cx, item, containing_item); write!(w, "", id); - w.write_str(""); + w.write_str("

"); render_assoc_item( w, item, @@ -1358,7 +1358,7 @@ fn render_impl( ItemType::Impl, cx, ); - w.write_str(""); + w.write_str("

"); w.write_str(""); } } @@ -1371,7 +1371,7 @@ fn render_impl( id, item_type, in_trait_class ); write!(w, "", id); - w.write_str(""); + w.write_str("

"); assoc_type( w, item, @@ -1381,7 +1381,7 @@ fn render_impl( "", cx, ); - w.write_str(""); + w.write_str("

"); w.write_str(""); } clean::AssocConstItem(ref ty, ref default) => { @@ -1394,7 +1394,7 @@ fn render_impl( ); render_rightside(w, cx, item, containing_item); write!(w, "", id); - w.write_str(""); + w.write_str("

"); assoc_const( w, item, @@ -1404,7 +1404,7 @@ fn render_impl( "", cx, ); - w.write_str(""); + w.write_str("

"); w.write_str(""); } clean::AssocTypeItem(ref bounds, ref default) => { @@ -1412,7 +1412,7 @@ fn render_impl( let id = cx.derive_id(source_id.clone()); write!(w, "
", id, item_type, in_trait_class,); write!(w, "", id); - w.write_str(""); + w.write_str("

"); assoc_type( w, item, @@ -1422,7 +1422,7 @@ fn render_impl( "", cx, ); - w.write_str(""); + w.write_str("

"); w.write_str("
"); } clean::StrippedItem(..) => return, @@ -1613,7 +1613,7 @@ pub(crate) fn render_impl_summary( write!(w, "
", id, aliases); render_rightside(w, cx, &i.impl_item, containing_item); write!(w, "", id); - write!(w, ""); + write!(w, "

"); if let Some(use_absolute) = use_absolute { write!(w, "{}", i.inner_impl().print(use_absolute, cx)); @@ -1629,7 +1629,7 @@ pub(crate) fn render_impl_summary( } else { write!(w, "{}", i.inner_impl().print(false, cx)); } - write!(w, ""); + write!(w, "

"); let is_trait = i.inner_impl().trait_.is_some(); if is_trait { diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 552958d5e402b..50793acbbf0f1 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -621,9 +621,9 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra render_stability_since(w, m, t, cx.tcx()); write_srclink(cx, m, w); write!(w, "
"); - write!(w, ""); + write!(w, "

"); render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl, cx); - w.write_str(""); + w.write_str("

"); w.write_str(""); if toggled { write!(w, ""); diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 6672093eb7bc6..f124d7aec6c1e 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -146,6 +146,13 @@ h1.fqn > .in-band > a:hover { h2, h3, h4 { border-bottom: 1px solid; } +h3.code-header, h4.code-header { + font-size: 1em; + font-weight: 600; + border: none; + padding: 0; + margin: 0; +} .impl, .impl-items .method, .methods .method, @@ -233,7 +240,7 @@ details:not(.rustdoc-toggle) summary { margin-bottom: .6em; } -code, pre, a.test-arrow { +code, pre, a.test-arrow, .code-header { font-family: "Source Code Pro", monospace; } .docblock code, .docblock-short code { @@ -520,7 +527,7 @@ nav.sub { font-weight: normal; } -.method > code, .trait-impl > code, .invisible > code { +.method > .code-header, .trait-impl > .code-header, .invisible > .code-header { max-width: calc(100% - 41px); display: block; } @@ -536,7 +543,7 @@ nav.sub { padding: 0px; } -.in-band > code { +.in-band > code, .in-band > .code-header { display: inline-block; } @@ -742,7 +749,7 @@ a { } .invisible > .srclink, -.method > code + .srclink { +.method > .code-header + .srclink { position: absolute; top: 0; right: 0; @@ -1103,7 +1110,7 @@ a.test-arrow:hover{ left: -10px; } -:target > code { +:target > code, :target > .code-header { opacity: 1; } diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 38ddbb3ad7427..869aff5376649 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -706,8 +706,9 @@ function hideThemeButtonState() { } } - var code = document.createElement("code"); + var code = document.createElement("h3"); code.innerHTML = struct.text; + addClass(code, "code-header"); addClass(code, "in-band"); onEachLazy(code.getElementsByTagName("a"), function(elem) {