Skip to content

Commit def144c

Browse files
jshaManishearth
authored andcommitted
Improve CSS for "hide contents, not items"
Introduce a first use of the `<details>` and `<summary>` tags as replacements for the JS-built toggles. I think this has the potential to replace all the JS toggles and generally clean up the JS, CSS, and HTML. Split rendering of attributes into two cases: in the case where they are rendered as descendents of a `<pre>` tag, where they use indent spaces and newlines for formatting, matching their surrounding markup. In the case where they are rendered as descendants of a `<code>` tag, they are rendered as `<div>`. This let me clean up some fragile CSS that was adjusting the margin-left of attributes depending on context. Remove toggles for attributes. With the ALLOWED_ATTRIBUTES filter, it's rare for an item to have more than one attribute, so hiding attributes behind a toggle doesn't save any screen space in the common case. Fix a couple of invocations of `matches!` that didn't compile on my machine. Fix a boolean for the JS `createToggle` call that was causing "Expand description" to show up spuriously on already-expanded descriptions. Add JS for auto-hide settings and hide all / show all. Remove a z-index property and some font color tweaks made unnecessary by the <details> toggles. Add CSS for the <details> toggles.
1 parent 846a4e9 commit def144c

File tree

8 files changed

+116
-130
lines changed

8 files changed

+116
-130
lines changed

src/librustdoc/html/render/mod.rs

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ use std::path::PathBuf;
4343
use std::str;
4444
use std::string::ToString;
4545

46-
use itertools::Itertools;
4746
use rustc_ast_pretty::pprust;
4847
use rustc_attr::{Deprecation, StabilityLevel};
4948
use rustc_data_structures::fx::FxHashSet;
@@ -487,7 +486,6 @@ fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result<Strin
487486
)
488487
.into(),
489488
("auto-hide-large-items", "Auto-hide item contents for large items.", true).into(),
490-
("auto-hide-attributes", "Auto-hide item attributes.", true).into(),
491489
("auto-hide-method-docs", "Auto-hide item methods' documentation", false).into(),
492490
("auto-hide-trait-implementations", "Auto-hide trait implementation documentation", true)
493491
.into(),
@@ -936,19 +934,21 @@ fn render_assoc_item(
936934
+ name.as_str().len()
937935
+ generics_len;
938936

939-
let (indent, end_newline) = if parent == ItemType::Trait {
937+
let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
940938
header_len += 4;
941-
(4, false)
939+
let indent_str = " ";
940+
render_attributes_in_pre(w, meth, indent_str);
941+
(4, indent_str, false)
942942
} else {
943-
(0, true)
943+
render_attributes_in_code(w, meth);
944+
(0, "", true)
944945
};
945-
render_attributes(w, meth, false);
946946
w.reserve(header_len + "<a href=\"\" class=\"fnname\">{".len() + "</a>".len());
947947
write!(
948948
w,
949949
"{}{}{}{}{}{}{}fn <a href=\"{href}\" class=\"fnname\">{name}</a>\
950950
{generics}{decl}{notable_traits}{where_clause}",
951-
if parent == ItemType::Trait { " " } else { "" },
951+
indent_str,
952952
vis,
953953
constness,
954954
asyncness,
@@ -1004,35 +1004,33 @@ const ALLOWED_ATTRIBUTES: &[Symbol] = &[
10041004
sym::non_exhaustive,
10051005
];
10061006

1007-
// The `top` parameter is used when generating the item declaration to ensure it doesn't have a
1008-
// left padding. For example:
1009-
//
1010-
// #[foo] <----- "top" attribute
1011-
// struct Foo {
1012-
// #[bar] <---- not "top" attribute
1013-
// bar: usize,
1014-
// }
1015-
fn render_attributes(w: &mut Buffer, it: &clean::Item, top: bool) {
1016-
let attrs = it
1017-
.attrs
1007+
fn attributes(it: &clean::Item) -> Vec<String> {
1008+
it.attrs
10181009
.other_attrs
10191010
.iter()
10201011
.filter_map(|attr| {
10211012
if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) {
1022-
Some(pprust::attribute_to_string(&attr))
1013+
Some(pprust::attribute_to_string(&attr).replace("\n", "").replace(" ", " "))
10231014
} else {
10241015
None
10251016
}
10261017
})
1027-
.join("\n");
1018+
.collect()
1019+
}
10281020

1029-
if !attrs.is_empty() {
1030-
write!(
1031-
w,
1032-
"<span class=\"docblock attributes{}\">{}</span>",
1033-
if top { " top-attr" } else { "" },
1034-
&attrs
1035-
);
1021+
// When an attribute is rendered inside a `<pre>` tag, it is formatted using
1022+
// a whitespace prefix and newline.
1023+
fn render_attributes_in_pre(w: &mut Buffer, it: &clean::Item, prefix: &str) {
1024+
for a in attributes(it) {
1025+
write!(w, "{}{}\n", prefix, a);
1026+
}
1027+
}
1028+
1029+
// When an attribute is rendered inside a <code> tag, it is formatted using
1030+
// a div to produce a newline after it.
1031+
fn render_attributes_in_code(w: &mut Buffer, it: &clean::Item) {
1032+
for a in attributes(it) {
1033+
write!(w, "<div>{}</div>", a);
10361034
}
10371035
}
10381036

src/librustdoc/html/render/print_item.rs

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use rustc_span::symbol::{kw, sym, Symbol};
1111

1212
use super::{
1313
collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl,
14-
render_assoc_item, render_assoc_items, render_attributes, render_impl,
15-
render_stability_since_raw, write_srclink, AssocItemLink, Context,
14+
render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre,
15+
render_impl, render_stability_since_raw, write_srclink, AssocItemLink, Context,
1616
};
1717
use crate::clean::{self, GetDefId};
1818
use crate::formats::cache::Cache;
@@ -138,11 +138,15 @@ fn should_hide_fields(n_fields: usize) -> bool {
138138
}
139139

140140
fn toggle_open(w: &mut Buffer, text: &str) {
141-
write!(w, "<div class=\"docblock type-contents-toggle\" data-toggle-text=\"{}\">", text);
141+
write!(
142+
w,
143+
"<details class=\"type-contents-toggle\"><summary class=\"hideme\"><span>Show {}</span></summary>",
144+
text
145+
);
142146
}
143147

144148
fn toggle_close(w: &mut Buffer) {
145-
w.write_str("</div>");
149+
w.write_str("</details>");
146150
}
147151

148152
fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) {
@@ -391,7 +395,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
391395
)
392396
.len();
393397
w.write_str("<pre class=\"rust fn\">");
394-
render_attributes(w, it, false);
398+
render_attributes_in_pre(w, it, "");
395399
write!(
396400
w,
397401
"{vis}{constness}{asyncness}{unsafety}{abi}fn \
@@ -420,7 +424,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
420424
// Output the trait definition
421425
wrap_into_docblock(w, |w| {
422426
w.write_str("<pre class=\"rust trait\">");
423-
render_attributes(w, it, true);
427+
render_attributes_in_pre(w, it, "");
424428
write!(
425429
w,
426430
"{}{}{}trait {}{}{}",
@@ -729,7 +733,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
729733

730734
fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TraitAlias) {
731735
w.write_str("<pre class=\"rust trait-alias\">");
732-
render_attributes(w, it, false);
736+
render_attributes_in_pre(w, it, "");
733737
write!(
734738
w,
735739
"trait {}{}{} = {};</pre>",
@@ -750,7 +754,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
750754

751755
fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
752756
w.write_str("<pre class=\"rust opaque\">");
753-
render_attributes(w, it, false);
757+
render_attributes_in_pre(w, it, "");
754758
write!(
755759
w,
756760
"type {}{}{where_clause} = impl {bounds};</pre>",
@@ -771,7 +775,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
771775

772776
fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
773777
w.write_str("<pre class=\"rust typedef\">");
774-
render_attributes(w, it, false);
778+
render_attributes_in_pre(w, it, "");
775779
write!(
776780
w,
777781
"type {}{}{where_clause} = {type_};</pre>",
@@ -793,7 +797,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T
793797
fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) {
794798
wrap_into_docblock(w, |w| {
795799
w.write_str("<pre class=\"rust union\">");
796-
render_attributes(w, it, true);
800+
render_attributes_in_pre(w, it, "");
797801
render_union(w, it, Some(&s.generics), &s.fields, "", true, cx);
798802
w.write_str("</pre>")
799803
});
@@ -839,7 +843,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
839843
fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) {
840844
wrap_into_docblock(w, |w| {
841845
w.write_str("<pre class=\"rust enum\">");
842-
render_attributes(w, it, true);
846+
render_attributes_in_pre(w, it, "");
843847
write!(
844848
w,
845849
"{}enum {}{}{}",
@@ -1019,7 +1023,7 @@ fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
10191023

10201024
fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::Constant) {
10211025
w.write_str("<pre class=\"rust const\">");
1022-
render_attributes(w, it, false);
1026+
render_attributes_in_code(w, it);
10231027

10241028
write!(
10251029
w,
@@ -1058,7 +1062,7 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::
10581062
fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) {
10591063
wrap_into_docblock(w, |w| {
10601064
w.write_str("<pre class=\"rust struct\">");
1061-
render_attributes(w, it, true);
1065+
render_attributes_in_code(w, it);
10621066
render_struct(w, it, Some(&s.generics), s.struct_type, &s.fields, "", true, cx);
10631067
w.write_str("</pre>")
10641068
});
@@ -1107,7 +1111,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
11071111

11081112
fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Static) {
11091113
w.write_str("<pre class=\"rust static\">");
1110-
render_attributes(w, it, false);
1114+
render_attributes_in_code(w, it);
11111115
write!(
11121116
w,
11131117
"{vis}static {mutability}{name}: {typ}</pre>",
@@ -1121,7 +1125,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
11211125

11221126
fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
11231127
w.write_str("<pre class=\"rust foreigntype\">extern {\n");
1124-
render_attributes(w, it, false);
1128+
render_attributes_in_code(w, it);
11251129
write!(
11261130
w,
11271131
" {}type {};\n}}</pre>",
@@ -1304,10 +1308,8 @@ fn render_union(
13041308
}
13051309

13061310
write!(w, " {{\n{}", tab);
1307-
let count_fields = fields
1308-
.iter()
1309-
.filter(|f| matches!(clean::StructFieldItem(..), *f.kind))
1310-
.count();
1311+
let count_fields =
1312+
fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count();
13111313
let toggle = should_hide_fields(count_fields);
13121314
if toggle {
13131315
toggle_open(w, "fields");
@@ -1361,10 +1363,8 @@ fn render_struct(
13611363
write!(w, "{}", print_where_clause(g, cx.cache(), cx.tcx(), 0, true),)
13621364
}
13631365
w.write_str(" {");
1364-
let count_fields = fields
1365-
.iter()
1366-
.filter(|f| matches!(clean::StructFieldItem(..) = *f.kind))
1367-
.count();
1366+
let count_fields =
1367+
fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count();
13681368
let has_visible_fields = count_fields > 0;
13691369
let toggle = should_hide_fields(count_fields);
13701370
if toggle {

src/librustdoc/html/static/main.js

Lines changed: 16 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// ignore-tidy-filelength
21
// Local js definitions:
32
/* global addClass, getSettingValue, hasClass */
43
/* global onEach, onEachLazy, hasOwnProperty, removeClass, updateLocalStorage */
@@ -2316,6 +2315,9 @@ function hideThemeButtonState() {
23162315
if (hasClass(innerToggle, "will-expand")) {
23172316
updateLocalStorage("rustdoc-collapse", "false");
23182317
removeClass(innerToggle, "will-expand");
2318+
onEachLazy(document.getElementsByTagName("details"), function(e) {
2319+
e.open = true;
2320+
});
23192321
onEveryMatchingChild(innerToggle, "inner", function(e) {
23202322
e.innerHTML = labelForToggleButton(false);
23212323
});
@@ -2328,6 +2330,9 @@ function hideThemeButtonState() {
23282330
} else {
23292331
updateLocalStorage("rustdoc-collapse", "true");
23302332
addClass(innerToggle, "will-expand");
2333+
onEachLazy(document.getElementsByTagName("details"), function(e) {
2334+
e.open = false;
2335+
});
23312336
onEveryMatchingChild(innerToggle, "inner", function(e) {
23322337
var parent = e.parentNode;
23332338
var superParent = null;
@@ -2569,6 +2574,7 @@ function hideThemeButtonState() {
25692574
var toggle = createSimpleToggle(false);
25702575
var hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true";
25712576
var hideImplementors = getSettingValue("auto-collapse-implementors") !== "false";
2577+
let hideLargeItemContents = getSettingValue("auto-hide-large-items") !== "false";
25722578

25732579
var func = function(e) {
25742580
var next = e.nextElementSibling;
@@ -2615,6 +2621,14 @@ function hideThemeButtonState() {
26152621
onEachLazy(document.getElementsByClassName("associatedconstant"), func);
26162622
onEachLazy(document.getElementsByClassName("impl"), funcImpl);
26172623
var impl_call = function() {};
2624+
// Large items are hidden by default in the HTML. If the setting overrides that, show 'em.
2625+
if (!hideLargeItemContents) {
2626+
onEachLazy(document.getElementsByTagName("details"), function (e) {
2627+
if (hasClass(e, "type-contents-toggle")) {
2628+
e.open = true;
2629+
}
2630+
});
2631+
}
26182632
if (hideMethodDocs === true) {
26192633
impl_call = function(e, newToggle) {
26202634
if (e.id.match(/^impl(?:-\d+)?$/) === null) {
@@ -2703,14 +2717,6 @@ function hideThemeButtonState() {
27032717
}
27042718
});
27052719
}
2706-
} else if (hasClass(e, "type-contents-toggle")) {
2707-
let text = e.getAttribute("data-toggle-text");
2708-
let hideItemContents = getSettingValue("auto-hide-large-items") !== "false";
2709-
let tog = createToggle(toggle, `Show ${text}`, null, "", !hideItemContents);
2710-
e.parentNode.insertBefore(tog, e);
2711-
if (hideItemContents) {
2712-
collapseDocs(e.previousSibling.childNodes[0], "toggle");
2713-
}
27142720
}
27152721
if (e.parentNode.id === "main") {
27162722
var otherMessage = "";
@@ -2744,7 +2750,7 @@ function hideThemeButtonState() {
27442750
otherMessage,
27452751
fontSize,
27462752
extraClass,
2747-
false),
2753+
true),
27482754
e);
27492755
if (hasClass(e, "non-exhaustive") === true) {
27502756
collapseDocs(e.previousSibling.childNodes[0], "toggle");
@@ -2763,38 +2769,6 @@ function hideThemeButtonState() {
27632769
}
27642770
}());
27652771

2766-
function createToggleWrapper(tog) {
2767-
var span = document.createElement("span");
2768-
span.className = "toggle-label";
2769-
span.style.display = "none";
2770-
span.innerHTML = "&nbsp;Expand&nbsp;attributes";
2771-
tog.appendChild(span);
2772-
2773-
var wrapper = document.createElement("div");
2774-
wrapper.className = "toggle-wrapper toggle-attributes";
2775-
wrapper.appendChild(tog);
2776-
return wrapper;
2777-
}
2778-
2779-
(function() {
2780-
// To avoid checking on "rustdoc-item-attributes" value on every loop...
2781-
var itemAttributesFunc = function() {};
2782-
if (getSettingValue("auto-hide-attributes") !== "false") {
2783-
itemAttributesFunc = function(x) {
2784-
collapseDocs(x.previousSibling.childNodes[0], "toggle");
2785-
};
2786-
}
2787-
var attributesToggle = createToggleWrapper(createSimpleToggle(false));
2788-
onEachLazy(main.getElementsByClassName("attributes"), function(i_e) {
2789-
var attr_tog = attributesToggle.cloneNode(true);
2790-
if (hasClass(i_e, "top-attr") === true) {
2791-
addClass(attr_tog, "top-attr");
2792-
}
2793-
i_e.parentNode.insertBefore(attr_tog, i_e);
2794-
itemAttributesFunc(i_e);
2795-
});
2796-
}());
2797-
27982772
(function() {
27992773
// To avoid checking on "rustdoc-line-numbers" value on every loop...
28002774
var lineNumbersFunc = function() {};

0 commit comments

Comments
 (0)