Skip to content

Commit 79bd6be

Browse files
committed
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 790218f commit 79bd6be

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
@@ -44,7 +44,6 @@ use std::str;
4444
use std::string::ToString;
4545
use std::sync::mpsc::Receiver;
4646

47-
use itertools::Itertools;
4847
use rustc_ast_pretty::pprust;
4948
use rustc_attr::{Deprecation, StabilityLevel};
5049
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -575,7 +574,6 @@ fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result<Strin
575574
)
576575
.into(),
577576
("auto-hide-large-items", "Auto-hide item contents for large items.", true).into(),
578-
("auto-hide-attributes", "Auto-hide item attributes.", true).into(),
579577
("auto-hide-method-docs", "Auto-hide item methods' documentation", false).into(),
580578
("auto-hide-trait-implementations", "Auto-hide trait implementation documentation", true)
581579
.into(),
@@ -1011,18 +1009,20 @@ fn render_assoc_item(
10111009
g.print(cx.cache())
10121010
)
10131011
.len();
1014-
let (indent, end_newline) = if parent == ItemType::Trait {
1012+
let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
10151013
header_len += 4;
1016-
(4, false)
1014+
let indent_str = " ";
1015+
render_attributes_in_pre(w, meth, indent_str);
1016+
(4, indent_str, false)
10171017
} else {
1018-
(0, true)
1018+
render_attributes_in_code(w, meth);
1019+
(0, "", true)
10191020
};
1020-
render_attributes(w, meth, false);
10211021
write!(
10221022
w,
10231023
"{}{}{}{}{}{}{}fn <a href=\"{href}\" class=\"fnname\">{name}</a>\
10241024
{generics}{decl}{spotlight}{where_clause}",
1025-
if parent == ItemType::Trait { " " } else { "" },
1025+
indent_str,
10261026
meth.visibility.print_with_space(cx.tcx(), meth.def_id, cx.cache()),
10271027
header.constness.print_with_space(),
10281028
header.asyncness.print_with_space(),
@@ -1078,35 +1078,33 @@ const ALLOWED_ATTRIBUTES: &[Symbol] = &[
10781078
sym::non_exhaustive,
10791079
];
10801080

1081-
// The `top` parameter is used when generating the item declaration to ensure it doesn't have a
1082-
// left padding. For example:
1083-
//
1084-
// #[foo] <----- "top" attribute
1085-
// struct Foo {
1086-
// #[bar] <---- not "top" attribute
1087-
// bar: usize,
1088-
// }
1089-
fn render_attributes(w: &mut Buffer, it: &clean::Item, top: bool) {
1090-
let attrs = it
1091-
.attrs
1081+
fn attributes(it: &clean::Item) -> Vec<String> {
1082+
it.attrs
10921083
.other_attrs
10931084
.iter()
10941085
.filter_map(|attr| {
10951086
if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) {
1096-
Some(pprust::attribute_to_string(&attr))
1087+
Some(pprust::attribute_to_string(&attr).replace("\n", "").replace(" ", " "))
10971088
} else {
10981089
None
10991090
}
11001091
})
1101-
.join("\n");
1092+
.collect()
1093+
}
11021094

1103-
if !attrs.is_empty() {
1104-
write!(
1105-
w,
1106-
"<span class=\"docblock attributes{}\">{}</span>",
1107-
if top { " top-attr" } else { "" },
1108-
&attrs
1109-
);
1095+
// When an attribute is rendered inside a `<pre>` tag, it is formatted using
1096+
// a whitespace prefix and newline.
1097+
fn render_attributes_in_pre(w: &mut Buffer, it: &clean::Item, prefix: &str) {
1098+
for a in attributes(it) {
1099+
write!(w, "{}{}\n", prefix, a);
1100+
}
1101+
}
1102+
1103+
// When an attribute is rendered inside a <code> tag, it is formatted using
1104+
// a div to produce a newline after it.
1105+
fn render_attributes_in_code(w: &mut Buffer, it: &clean::Item) {
1106+
for a in attributes(it) {
1107+
write!(w, "<div>{}</div>", a);
11101108
}
11111109
}
11121110

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, render_assoc_item,
14-
render_assoc_items, render_attributes, render_impl, render_stability_since_raw, spotlight_decl,
15-
write_srclink, AssocItemLink, Context,
14+
render_assoc_items, render_attributes_in_code, render_attributes_in_pre, render_impl,
15+
render_stability_since_raw, spotlight_decl, write_srclink, AssocItemLink, Context,
1616
};
1717
use crate::clean::{self, GetDefId};
1818
use crate::formats::cache::Cache;
@@ -137,11 +137,15 @@ fn should_hide_fields(n_fields: usize) -> bool {
137137
}
138138

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

143147
fn toggle_close(w: &mut Buffer) {
144-
w.write_str("</div>");
148+
w.write_str("</details>");
145149
}
146150

147151
fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) {
@@ -390,7 +394,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
390394
)
391395
.len();
392396
w.write_str("<pre class=\"rust fn\">");
393-
render_attributes(w, it, false);
397+
render_attributes_in_pre(w, it, "");
394398
write!(
395399
w,
396400
"{vis}{constness}{asyncness}{unsafety}{abi}fn \
@@ -421,7 +425,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
421425
// Output the trait definition
422426
wrap_into_docblock(w, |w| {
423427
w.write_str("<pre class=\"rust trait\">");
424-
render_attributes(w, it, true);
428+
render_attributes_in_pre(w, it, "");
425429
write!(
426430
w,
427431
"{}{}{}trait {}{}{}",
@@ -731,7 +735,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
731735

732736
fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TraitAlias) {
733737
w.write_str("<pre class=\"rust trait-alias\">");
734-
render_attributes(w, it, false);
738+
render_attributes_in_pre(w, it, "");
735739
write!(
736740
w,
737741
"trait {}{}{} = {};</pre>",
@@ -752,7 +756,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
752756

753757
fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
754758
w.write_str("<pre class=\"rust opaque\">");
755-
render_attributes(w, it, false);
759+
render_attributes_in_pre(w, it, "");
756760
write!(
757761
w,
758762
"type {}{}{where_clause} = impl {bounds};</pre>",
@@ -774,7 +778,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
774778

775779
fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
776780
w.write_str("<pre class=\"rust typedef\">");
777-
render_attributes(w, it, false);
781+
render_attributes_in_pre(w, it, "");
778782
write!(
779783
w,
780784
"type {}{}{where_clause} = {type_};</pre>",
@@ -797,7 +801,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T
797801
fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) {
798802
wrap_into_docblock(w, |w| {
799803
w.write_str("<pre class=\"rust union\">");
800-
render_attributes(w, it, true);
804+
render_attributes_in_pre(w, it, "");
801805
render_union(w, it, Some(&s.generics), &s.fields, "", true, cx);
802806
w.write_str("</pre>")
803807
});
@@ -843,7 +847,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
843847
fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) {
844848
wrap_into_docblock(w, |w| {
845849
w.write_str("<pre class=\"rust enum\">");
846-
render_attributes(w, it, true);
850+
render_attributes_in_pre(w, it, "");
847851
write!(
848852
w,
849853
"{}enum {}{}{}",
@@ -1023,7 +1027,7 @@ fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
10231027

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

10281032
write!(
10291033
w,
@@ -1059,7 +1063,7 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::
10591063
fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) {
10601064
wrap_into_docblock(w, |w| {
10611065
w.write_str("<pre class=\"rust struct\">");
1062-
render_attributes(w, it, true);
1066+
render_attributes_in_code(w, it);
10631067
render_struct(w, it, Some(&s.generics), s.struct_type, &s.fields, "", true, cx);
10641068
w.write_str("</pre>")
10651069
});
@@ -1108,7 +1112,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
11081112

11091113
fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Static) {
11101114
w.write_str("<pre class=\"rust static\">");
1111-
render_attributes(w, it, false);
1115+
render_attributes_in_code(w, it);
11121116
write!(
11131117
w,
11141118
"{vis}static {mutability}{name}: {typ}</pre>",
@@ -1122,7 +1126,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
11221126

11231127
fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
11241128
w.write_str("<pre class=\"rust foreigntype\">extern {\n");
1125-
render_attributes(w, it, false);
1129+
render_attributes_in_code(w, it);
11261130
write!(
11271131
w,
11281132
" {}type {};\n}}</pre>",
@@ -1295,10 +1299,8 @@ fn render_union(
12951299
}
12961300

12971301
write!(w, " {{\n{}", tab);
1298-
let count_fields = fields
1299-
.iter()
1300-
.filter(|f| matches!(clean::StructFieldItem(..), *f.kind))
1301-
.count();
1302+
let count_fields =
1303+
fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count();
13021304
let toggle = should_hide_fields(count_fields);
13031305
if toggle {
13041306
toggle_open(w, "fields");
@@ -1356,10 +1358,8 @@ fn render_struct(
13561358
)
13571359
}
13581360
w.write_str(" {");
1359-
let count_fields = fields
1360-
.iter()
1361-
.filter(|f| matches!(clean::StructFieldItem(..) = *f.kind))
1362-
.count();
1361+
let count_fields =
1362+
fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count();
13631363
let has_visible_fields = count_fields > 0;
13641364
let toggle = should_hide_fields(count_fields);
13651365
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 */
@@ -2252,6 +2251,9 @@ function defocusSearchBar() {
22522251
if (hasClass(innerToggle, "will-expand")) {
22532252
updateLocalStorage("rustdoc-collapse", "false");
22542253
removeClass(innerToggle, "will-expand");
2254+
onEachLazy(document.getElementsByTagName("details"), function(e) {
2255+
e.open = true;
2256+
});
22552257
onEveryMatchingChild(innerToggle, "inner", function(e) {
22562258
e.innerHTML = labelForToggleButton(false);
22572259
});
@@ -2264,6 +2266,9 @@ function defocusSearchBar() {
22642266
} else {
22652267
updateLocalStorage("rustdoc-collapse", "true");
22662268
addClass(innerToggle, "will-expand");
2269+
onEachLazy(document.getElementsByTagName("details"), function(e) {
2270+
e.open = false;
2271+
});
22672272
onEveryMatchingChild(innerToggle, "inner", function(e) {
22682273
var parent = e.parentNode;
22692274
var superParent = null;
@@ -2505,6 +2510,7 @@ function defocusSearchBar() {
25052510
var toggle = createSimpleToggle(false);
25062511
var hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true";
25072512
var hideImplementors = getSettingValue("auto-collapse-implementors") !== "false";
2513+
let hideLargeItemContents = getSettingValue("auto-hide-large-items") !== "false";
25082514

25092515
var func = function(e) {
25102516
var next = e.nextElementSibling;
@@ -2551,6 +2557,14 @@ function defocusSearchBar() {
25512557
onEachLazy(document.getElementsByClassName("associatedconstant"), func);
25522558
onEachLazy(document.getElementsByClassName("impl"), funcImpl);
25532559
var impl_call = function() {};
2560+
// Large items are hidden by default in the HTML. If the setting overrides that, show 'em.
2561+
if (!hideLargeItemContents) {
2562+
onEachLazy(document.getElementsByTagName("details"), function (e) {
2563+
if (hasClass(e, "type-contents-toggle")) {
2564+
e.open = true;
2565+
}
2566+
});
2567+
}
25542568
if (hideMethodDocs === true) {
25552569
impl_call = function(e, newToggle) {
25562570
if (e.id.match(/^impl(?:-\d+)?$/) === null) {
@@ -2639,14 +2653,6 @@ function defocusSearchBar() {
26392653
}
26402654
});
26412655
}
2642-
} else if (hasClass(e, "type-contents-toggle")) {
2643-
let text = e.getAttribute("data-toggle-text");
2644-
let hideItemContents = getSettingValue("auto-hide-large-items") !== "false";
2645-
let tog = createToggle(toggle, `Show ${text}`, null, "", !hideItemContents);
2646-
e.parentNode.insertBefore(tog, e);
2647-
if (hideItemContents) {
2648-
collapseDocs(e.previousSibling.childNodes[0], "toggle");
2649-
}
26502656
}
26512657
if (e.parentNode.id === "main") {
26522658
var otherMessage = "";
@@ -2680,7 +2686,7 @@ function defocusSearchBar() {
26802686
otherMessage,
26812687
fontSize,
26822688
extraClass,
2683-
false),
2689+
true),
26842690
e);
26852691
if (hasClass(e, "non-exhaustive") === true) {
26862692
collapseDocs(e.previousSibling.childNodes[0], "toggle");
@@ -2699,38 +2705,6 @@ function defocusSearchBar() {
26992705
}
27002706
}());
27012707

2702-
function createToggleWrapper(tog) {
2703-
var span = document.createElement("span");
2704-
span.className = "toggle-label";
2705-
span.style.display = "none";
2706-
span.innerHTML = "&nbsp;Expand&nbsp;attributes";
2707-
tog.appendChild(span);
2708-
2709-
var wrapper = document.createElement("div");
2710-
wrapper.className = "toggle-wrapper toggle-attributes";
2711-
wrapper.appendChild(tog);
2712-
return wrapper;
2713-
}
2714-
2715-
(function() {
2716-
// To avoid checking on "rustdoc-item-attributes" value on every loop...
2717-
var itemAttributesFunc = function() {};
2718-
if (getSettingValue("auto-hide-attributes") !== "false") {
2719-
itemAttributesFunc = function(x) {
2720-
collapseDocs(x.previousSibling.childNodes[0], "toggle");
2721-
};
2722-
}
2723-
var attributesToggle = createToggleWrapper(createSimpleToggle(false));
2724-
onEachLazy(main.getElementsByClassName("attributes"), function(i_e) {
2725-
var attr_tog = attributesToggle.cloneNode(true);
2726-
if (hasClass(i_e, "top-attr") === true) {
2727-
addClass(attr_tog, "top-attr");
2728-
}
2729-
i_e.parentNode.insertBefore(attr_tog, i_e);
2730-
itemAttributesFunc(i_e);
2731-
});
2732-
}());
2733-
27342708
(function() {
27352709
// To avoid checking on "rustdoc-line-numbers" value on every loop...
27362710
var lineNumbersFunc = function() {};

0 commit comments

Comments
 (0)