Skip to content

Commit 09102d5

Browse files
Handle notable trait popup differently
1 parent 3ee016a commit 09102d5

File tree

9 files changed

+152
-53
lines changed

9 files changed

+152
-53
lines changed

src/librustdoc/html/format.rs

-4
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,6 @@ impl Buffer {
7979
self.buffer
8080
}
8181

82-
crate fn insert_str(&mut self, idx: usize, s: &str) {
83-
self.buffer.insert_str(idx, s);
84-
}
85-
8682
crate fn push_str(&mut self, s: &str) {
8783
self.buffer.push_str(s);
8884
}

src/librustdoc/html/markdown.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1439,6 +1439,8 @@ fn init_id_map() -> FxHashMap<String, usize> {
14391439
let mut map = FxHashMap::default();
14401440
// This is the list of IDs used in Javascript.
14411441
map.insert("help".to_owned(), 1);
1442+
// This is the ID used to generate the notable traits popup in Javascript.
1443+
map.insert("notable-traits-tooltiptext".to_owned(), 1);
14421444
// This is the list of IDs used in HTML generated in Rust (including the ones
14431445
// used in tera template files).
14441446
map.insert("mainThemeStyle".to_owned(), 1);

src/librustdoc/html/render/context.rs

+39-4
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ crate struct SharedContext<'tcx> {
129129
crate cache: Cache,
130130

131131
crate call_locations: AllCallLocations,
132+
/// The key is the notable trait text and the value is its index (we add it in the DOM so the
133+
/// JS knows which notable trait to pick).
134+
crate notable_traits: RefCell<FxHashMap<(String, String), usize>>,
132135
}
133136

134137
impl SharedContext<'_> {
@@ -369,6 +372,34 @@ impl<'tcx> Context<'tcx> {
369372
anchor = anchor
370373
))
371374
}
375+
376+
fn generate_notable_trait_index(&self, crate_name: &str) -> Result<(), Error> {
377+
let notable_traits = self.shared.notable_traits.borrow();
378+
if !notable_traits.is_empty() {
379+
// This is crate specific.
380+
let notable_traits_file = self.dst.join(crate_name).join("notable-traits.js");
381+
let out = "window.NOTABLE_TRAITS = [".to_owned();
382+
383+
// We need to put them back into a vec to sort them by their index.
384+
let mut notables = notable_traits.iter().collect::<Vec<_>>();
385+
notables.sort_by(|(_, pos1), (_, pos2)| pos1.cmp(pos2));
386+
387+
let mut out = notables.into_iter().fold(out, |mut acc, ((for_, content), pos)| {
388+
if *pos > 0 {
389+
acc.push(',');
390+
}
391+
acc.push_str(&format!(
392+
"[\"{}\",\"{}\"]",
393+
for_.replace("\"", "\\\""),
394+
content.replace("\\", "\\\\").replace("\"", "\\\""),
395+
));
396+
acc
397+
});
398+
out.push_str("];");
399+
self.shared.fs.write(notable_traits_file, out)?;
400+
}
401+
Ok(())
402+
}
372403
}
373404

374405
/// Generates the documentation for `crate` into the directory `dst`
@@ -493,6 +524,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
493524
span_correspondance_map: matches,
494525
cache,
495526
call_locations,
527+
notable_traits: RefCell::new(Default::default()),
496528
};
497529

498530
// Add the default themes to the `Vec` of stylepaths
@@ -549,9 +581,13 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
549581

550582
fn after_krate(&mut self) -> Result<(), Error> {
551583
let crate_name = self.tcx().crate_name(LOCAL_CRATE);
552-
let final_file = self.dst.join(&*crate_name.as_str()).join("all.html");
584+
let crate_name = crate_name.as_str();
585+
let crate_name: &str = &*crate_name;
586+
let final_file = self.dst.join(crate_name).join("all.html");
553587
let settings_file = self.dst.join("settings.html");
554588

589+
self.generate_notable_trait_index(crate_name)?;
590+
555591
let mut root_path = self.dst.to_str().expect("invalid path").to_owned();
556592
if !root_path.ends_with('/') {
557593
root_path.push('/');
@@ -618,10 +654,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
618654
self.shared.fs.write(settings_file, v)?;
619655
if let Some(ref redirections) = self.shared.redirections {
620656
if !redirections.borrow().is_empty() {
621-
let redirect_map_path =
622-
self.dst.join(&*crate_name.as_str()).join("redirect-map.json");
657+
let redirect_map_path = self.dst.join(crate_name).join("redirect-map.json");
623658
let paths = serde_json::to_string(&*redirections.borrow()).unwrap();
624-
self.shared.ensure_dir(&self.dst.join(&*crate_name.as_str()))?;
659+
self.shared.ensure_dir(&self.dst.join(crate_name))?;
625660
self.shared.fs.write(redirect_map_path, paths)?;
626661
}
627662
}

src/librustdoc/html/render/mod.rs

+38-17
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ mod write_shared;
3737
crate use self::context::*;
3838
crate use self::span_map::{collect_spans_and_sources, LinkFromSrc};
3939

40+
use std::collections::hash_map::Entry;
4041
use std::collections::VecDeque;
4142
use std::default::Default;
4243
use std::fmt;
@@ -1241,7 +1242,8 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
12411242
}
12421243

12431244
fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
1244-
let mut out = Buffer::html();
1245+
let mut out_for = Buffer::html();
1246+
let mut out_content = Buffer::html();
12451247

12461248
if let Some((did, ty)) = decl.output.as_return().and_then(|t| Some((t.def_id(cx.cache())?, t)))
12471249
{
@@ -1258,29 +1260,38 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
12581260
let trait_did = trait_.def_id();
12591261

12601262
if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable) {
1261-
if out.is_empty() {
1263+
if out_for.is_empty() {
12621264
write!(
1263-
&mut out,
1264-
"<div class=\"notable\">Notable traits for {}</div>\
1265-
<code class=\"content\">",
1266-
impl_.for_.print(cx)
1265+
&mut out_for,
1266+
"{}",
1267+
impl_.for_.print(cx),
1268+
// "<div class=\"notable\">Notable traits for {}</div>\
1269+
// <code class=\"content\">",
12671270
);
12681271
}
12691272

12701273
//use the "where" class here to make it small
12711274
write!(
1272-
&mut out,
1275+
&mut out_content,
12731276
"<span class=\"where fmt-newline\">{}</span>",
12741277
impl_.print(false, cx)
12751278
);
12761279
for it in &impl_.items {
12771280
if let clean::TypedefItem(ref tydef, _) = *it.kind {
1278-
out.push_str("<span class=\"where fmt-newline\"> ");
1281+
out_content.push_str("<span class=\"where fmt-newline\"> ");
12791282
let empty_set = FxHashSet::default();
12801283
let src_link =
12811284
AssocItemLink::GotoSource(trait_did.into(), &empty_set);
1282-
assoc_type(&mut out, it, &[], Some(&tydef.type_), src_link, "", cx);
1283-
out.push_str(";</span>");
1285+
assoc_type(
1286+
&mut out_content,
1287+
it,
1288+
&[],
1289+
Some(&tydef.type_),
1290+
src_link,
1291+
"",
1292+
cx,
1293+
);
1294+
out_content.push_str(";</span>");
12841295
}
12851296
}
12861297
}
@@ -1289,16 +1300,26 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
12891300
}
12901301
}
12911302

1292-
if !out.is_empty() {
1293-
out.insert_str(
1294-
0,
1295-
"<span class=\"notable-traits\"><span class=\"notable-traits-tooltip\">ⓘ\
1296-
<div class=\"notable-traits-tooltiptext\"><span class=\"docblock\">",
1303+
if !out_for.is_empty() && !out_content.is_empty() {
1304+
let mut notable_traits = cx.shared.notable_traits.borrow_mut();
1305+
1306+
let out_for = out_for.into_inner();
1307+
let out_content = out_content.into_inner();
1308+
let nb_notable = notable_traits.len();
1309+
let index = match notable_traits.entry((out_for, out_content)) {
1310+
Entry::Occupied(o) => *o.get(),
1311+
Entry::Vacant(v) => {
1312+
v.insert(nb_notable);
1313+
nb_notable
1314+
}
1315+
};
1316+
return format!(
1317+
"<span class=\"notable-traits\"><span class=\"notable-traits-tooltip\" data-index={}>ⓘ</span></span>",
1318+
index
12971319
);
1298-
out.push_str("</code></span></div></span></span>");
12991320
}
13001321

1301-
out.into_inner()
1322+
String::new()
13021323
}
13031324

13041325
#[derive(Clone, Copy, Debug)]

src/librustdoc/html/static/css/rustdoc.css

+4-10
Original file line numberDiff line numberDiff line change
@@ -1268,13 +1268,7 @@ h3.variant {
12681268
cursor: pointer;
12691269
}
12701270

1271-
.notable-traits:hover .notable-traits-tooltiptext,
1272-
.notable-traits .notable-traits-tooltiptext.force-tooltip {
1273-
display: inline-block;
1274-
}
1275-
1276-
.notable-traits .notable-traits-tooltiptext {
1277-
display: none;
1271+
#notable-traits-tooltiptext {
12781272
padding: 5px 3px 3px 3px;
12791273
border-radius: 6px;
12801274
margin-left: 5px;
@@ -1296,14 +1290,14 @@ h3.variant {
12961290
margin: 0;
12971291
}
12981292

1299-
.notable-traits .notable {
1293+
#notable-traits-tooltiptext .notable {
13001294
margin: 0;
13011295
margin-bottom: 13px;
13021296
font-size: 19px;
13031297
font-weight: 600;
13041298
}
13051299

1306-
.notable-traits .docblock code.content{
1300+
#notable-traits-tooltiptext code.content{
13071301
margin: 0;
13081302
padding: 0;
13091303
font-size: 20px;
@@ -1965,7 +1959,7 @@ details.rustdoc-toggle[open] > summary.hideme::after {
19651959
margin-top: 0;
19661960
}
19671961

1968-
.notable-traits .notable-traits-tooltiptext {
1962+
.notable-traits {
19691963
left: 0;
19701964
top: 100%;
19711965
}

src/librustdoc/html/static/css/themes/ayu.css

+2-2
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,12 @@ pre.ignore:hover, .information:hover + pre.ignore {
415415
border-color: transparent #314559 transparent transparent;
416416
}
417417

418-
.notable-traits-tooltiptext {
418+
#notable-traits-tooltiptext {
419419
background-color: #314559;
420420
border-color: #5c6773;
421421
}
422422

423-
.notable-traits-tooltiptext .notable {
423+
#notable-traits-tooltiptext .notable {
424424
border-bottom-color: #5c6773;
425425
}
426426

src/librustdoc/html/static/css/themes/dark.css

+2-2
Original file line numberDiff line numberDiff line change
@@ -363,12 +363,12 @@ pre.ignore:hover, .information:hover + pre.ignore {
363363
border-color: transparent black transparent transparent;
364364
}
365365

366-
.notable-traits-tooltiptext {
366+
#notable-traits-tooltiptext {
367367
background-color: #111;
368368
border-color: #777;
369369
}
370370

371-
.notable-traits-tooltiptext .notable {
371+
#notable-traits-tooltiptext .notable {
372372
border-bottom-color: #d2d2d2;
373373
}
374374

src/librustdoc/html/static/css/themes/light.css

+2-2
Original file line numberDiff line numberDiff line change
@@ -349,12 +349,12 @@ pre.ignore:hover, .information:hover + pre.ignore {
349349
border-color: transparent black transparent transparent;
350350
}
351351

352-
.notable-traits-tooltiptext {
352+
#notable-traits-tooltiptext {
353353
background-color: #eee;
354354
border-color: #999;
355355
}
356356

357-
.notable-traits-tooltiptext .notable {
357+
#notable-traits-tooltiptext .notable {
358358
border-bottom-color: #DDDDDD;
359359
}
360360

src/librustdoc/html/static/js/main.js

+63-12
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,13 @@ function hideThemeButtonState() {
171171
(function() {
172172
"use strict";
173173

174+
function loadScript(url, callback) {
175+
var script = document.createElement('script');
176+
script.src = url;
177+
script.onload = callback;
178+
document.head.append(script);
179+
}
180+
174181
window.searchState = {
175182
loadingText: "Loading search results...",
176183
input: document.getElementsByClassName("search-input")[0],
@@ -254,11 +261,6 @@ function hideThemeButtonState() {
254261
if (!searchState.input) {
255262
return;
256263
}
257-
function loadScript(url) {
258-
var script = document.createElement('script');
259-
script.src = url;
260-
document.head.append(script);
261-
}
262264

263265
var searchLoaded = false;
264266
function loadSearch() {
@@ -910,13 +912,6 @@ function hideThemeButtonState() {
910912
});
911913
});
912914

913-
onEachLazy(document.getElementsByClassName("notable-traits"), function(e) {
914-
e.onclick = function() {
915-
this.getElementsByClassName('notable-traits-tooltiptext')[0]
916-
.classList.toggle("force-tooltip");
917-
};
918-
});
919-
920915
var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
921916
if (sidebar_menu) {
922917
sidebar_menu.onclick = function() {
@@ -1010,6 +1005,62 @@ function hideThemeButtonState() {
10101005
onHashChange(null);
10111006
window.addEventListener("hashchange", onHashChange);
10121007
searchState.setup();
1008+
1009+
//
1010+
// Handling the notable traits popup.
1011+
//
1012+
function getNotablePopup(callback) {
1013+
var elemId = "notable-traits-tooltiptext";
1014+
var elem = document.getElementById(elemId);
1015+
1016+
if (!elem) {
1017+
// If the element cannot be found, it means it hasn't been created yet and that the
1018+
// notable traits index wasn't loaded either.
1019+
var script = getVar("root-path") + window.currentCrate + "/notable-traits.js";
1020+
loadScript(script, function() {
1021+
elem = document.createElement("code");
1022+
elem.id = elemId;
1023+
elem.classList = "docblock";
1024+
main.appendChild(elem);
1025+
callback(elem);
1026+
});
1027+
return;
1028+
}
1029+
callback(elem);
1030+
}
1031+
function showNotableTraitPopup(elem) {
1032+
getNotablePopup(function(popup) {
1033+
if (elem === window.currentNotableElem) {
1034+
popup.style.display = "none";
1035+
window.currentNotableElem = null;
1036+
return;
1037+
}
1038+
var elemRect = elem.getBoundingClientRect();
1039+
var containerRect = main.getBoundingClientRect();
1040+
1041+
var index = elem.getAttribute("data-index");
1042+
var notableTrait = window.NOTABLE_TRAITS[parseInt(index)];
1043+
1044+
popup.innerHTML = "<div class=\"notable\">Notable traits for " + notableTrait[0] + "</div><code class=\"content\">" + notableTrait[1] + "</code>";
1045+
popup.style.top = (elemRect.top - containerRect.top) + "px";
1046+
// In here, if the "i" is too much on the right, better put the popup on its left.
1047+
if (elem.offsetLeft > main.offsetWidth / 2) {
1048+
popup.style.left = "";
1049+
popup.style.right = (main.offsetWidth - elem.offsetLeft + 2) + "px";
1050+
} else {
1051+
popup.style.right = "";
1052+
popup.style.left = (elem.offsetLeft + 12) + "px";
1053+
}
1054+
popup.style.display = "";
1055+
window.currentNotableElem = elem;
1056+
});
1057+
}
1058+
1059+
onEachLazy(document.getElementsByClassName("notable-traits-tooltip"), function(e) {
1060+
e.onclick = function() {
1061+
showNotableTraitPopup(this);
1062+
};
1063+
});
10131064
}());
10141065

10151066
(function () {

0 commit comments

Comments
 (0)