diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index a3cbb5756fefc..da480ed7d887f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -79,10 +79,6 @@ impl Buffer { self.buffer } - crate fn insert_str(&mut self, idx: usize, s: &str) { - self.buffer.insert_str(idx, s); - } - crate fn push_str(&mut self, s: &str) { self.buffer.push_str(s); } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 545b409175ee6..487cf2a59df3b 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1439,6 +1439,8 @@ fn init_id_map() -> FxHashMap { let mut map = FxHashMap::default(); // This is the list of IDs used in Javascript. map.insert("help".to_owned(), 1); + // This is the ID used to generate the notable traits popup in Javascript. + map.insert("notable-traits-tooltiptext".to_owned(), 1); // This is the list of IDs used in HTML generated in Rust (including the ones // used in tera template files). map.insert("mainThemeStyle".to_owned(), 1); @@ -1458,6 +1460,7 @@ fn init_id_map() -> FxHashMap { map.insert("sidebar-vars".to_owned(), 1); map.insert("copy-path".to_owned(), 1); map.insert("TOC".to_owned(), 1); + map.insert("notable-traits".to_owned(), 1); // This is the list of IDs used by rustdoc sections (but still generated by // rustdoc). map.insert("fields".to_owned(), 1); diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 365d959ad9f3b..7bc5ea494cada 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -129,6 +129,9 @@ crate struct SharedContext<'tcx> { crate cache: Cache, crate call_locations: AllCallLocations, + /// The key is the notable trait text and the value is its index (we add it in the DOM so the + /// JS knows which notable trait to pick). + crate notable_traits: RefCell>, } impl SharedContext<'_> { @@ -493,6 +496,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { span_correspondance_map: matches, cache, call_locations, + notable_traits: RefCell::new(Default::default()), }; // Add the default themes to the `Vec` of stylepaths @@ -549,7 +553,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { fn after_krate(&mut self) -> Result<(), Error> { let crate_name = self.tcx().crate_name(LOCAL_CRATE); - let final_file = self.dst.join(&*crate_name.as_str()).join("all.html"); + let crate_name = crate_name.as_str(); + let crate_name: &str = &*crate_name; + let final_file = self.dst.join(crate_name).join("all.html"); let settings_file = self.dst.join("settings.html"); let mut root_path = self.dst.to_str().expect("invalid path").to_owned(); @@ -618,10 +624,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { self.shared.fs.write(settings_file, v)?; if let Some(ref redirections) = self.shared.redirections { if !redirections.borrow().is_empty() { - let redirect_map_path = - self.dst.join(&*crate_name.as_str()).join("redirect-map.json"); + let redirect_map_path = self.dst.join(crate_name).join("redirect-map.json"); let paths = serde_json::to_string(&*redirections.borrow()).unwrap(); - self.shared.ensure_dir(&self.dst.join(&*crate_name.as_str()))?; + self.shared.ensure_dir(&self.dst.join(crate_name))?; self.shared.fs.write(redirect_map_path, paths)?; } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 166e084012724..c7874dd625291 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -37,6 +37,7 @@ mod write_shared; crate use self::context::*; crate use self::span_map::{collect_spans_and_sources, LinkFromSrc}; +use std::collections::hash_map::Entry; use std::collections::VecDeque; use std::default::Default; use std::fmt; @@ -1241,7 +1242,8 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> } fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String { - let mut out = Buffer::html(); + let mut out_for = Buffer::html(); + let mut out_content = Buffer::html(); if let Some((did, ty)) = decl.output.as_return().and_then(|t| Some((t.def_id(cx.cache())?, t))) { @@ -1258,29 +1260,38 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String { let trait_did = trait_.def_id(); if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable) { - if out.is_empty() { + if out_for.is_empty() { write!( - &mut out, - "
Notable traits for {}
\ - ", - impl_.for_.print(cx) + &mut out_for, + "{}", + impl_.for_.print(cx), + // "
Notable traits for {}
\ + // ", ); } //use the "where" class here to make it small write!( - &mut out, + &mut out_content, "{}", impl_.print(false, cx) ); for it in &impl_.items { if let clean::TypedefItem(ref tydef, _) = *it.kind { - out.push_str(" "); + out_content.push_str(" "); let empty_set = FxHashSet::default(); let src_link = AssocItemLink::GotoSource(trait_did.into(), &empty_set); - assoc_type(&mut out, it, &[], Some(&tydef.type_), src_link, "", cx); - out.push_str(";"); + assoc_type( + &mut out_content, + it, + &[], + Some(&tydef.type_), + src_link, + "", + cx, + ); + out_content.push_str(";"); } } } @@ -1289,16 +1300,26 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String { } } - if !out.is_empty() { - out.insert_str( - 0, - "ⓘ\ -
", + if !out_for.is_empty() && !out_content.is_empty() { + let mut notable_traits = cx.shared.notable_traits.borrow_mut(); + + let out_for = out_for.into_inner(); + let out_content = out_content.into_inner(); + let nb_notable = notable_traits.len(); + let index = match notable_traits.entry((out_for, out_content)) { + Entry::Occupied(o) => *o.get(), + Entry::Vacant(v) => { + v.insert(nb_notable); + nb_notable + } + }; + return format!( + "", + index ); - out.push_str("
"); } - out.into_inner() + String::new() } #[derive(Clone, Copy, Debug)] diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 9943e23b9281c..22c080c63985b 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -171,6 +171,23 @@ pub(super) fn print_item( unreachable!(); } } + // We now write down all the notable traits DOM in one place that will be used by JS after. + let mut notable_traits = cx.shared.notable_traits.borrow_mut(); + if !notable_traits.is_empty() { + let mut notables = notable_traits.drain().collect::>(); + notables.sort_by(|(_, pos1), (_, pos2)| pos1.cmp(pos2)); + buf.write_str("
"); + for notable in notables { + buf.write_str(&format!( + "
\ +
Notable traits for {}
\ + {}\ +
", + notable.0.0, notable.0.1 + )); + } + buf.write_str("
"); + } } /// For large structs, enums, unions, etc, determine whether to hide their fields diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index cbb078f2ab377..ec1e239b0ac59 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1268,20 +1268,13 @@ h3.variant { cursor: pointer; } -.notable-traits:hover .notable-traits-tooltiptext, -.notable-traits .notable-traits-tooltiptext.force-tooltip { - display: inline-block; -} - -.notable-traits .notable-traits-tooltiptext { - display: none; +.notable-traits-tooltiptext { padding: 5px 3px 3px 3px; border-radius: 6px; margin-left: 5px; z-index: 10; font-size: 16px; cursor: default; - position: absolute; border: 1px solid; } @@ -1296,17 +1289,22 @@ h3.variant { margin: 0; } -.notable-traits .notable { +.notable-traits-tooltiptext .notable { margin: 0; margin-bottom: 13px; font-size: 19px; font-weight: 600; } +#notable-traits .notable-traits-tooltiptext { + display: none; + position: absolute; +} -.notable-traits .docblock code.content{ +.notable-traits-tooltiptext code.content{ margin: 0; padding: 0; font-size: 20px; + font-weight: 600; } /* Example code has the "Run" button that needs to be positioned relative to the pre */ @@ -1965,7 +1963,7 @@ details.rustdoc-toggle[open] > summary.hideme::after { margin-top: 0; } - .notable-traits .notable-traits-tooltiptext { + .notable-traits { left: 0; top: 100%; } diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 411a94ef2d1c1..6b0102ec19913 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -254,6 +254,7 @@ function hideThemeButtonState() { if (!searchState.input) { return; } + function loadScript(url) { var script = document.createElement('script'); script.src = url; @@ -910,13 +911,6 @@ function hideThemeButtonState() { }); }); - onEachLazy(document.getElementsByClassName("notable-traits"), function(e) { - e.onclick = function() { - this.getElementsByClassName('notable-traits-tooltiptext')[0] - .classList.toggle("force-tooltip"); - }; - }); - var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0]; if (sidebar_menu) { sidebar_menu.onclick = function() { @@ -1010,6 +1004,44 @@ function hideThemeButtonState() { onHashChange(null); window.addEventListener("hashchange", onHashChange); searchState.setup(); + + // + // Handling the notable traits popup. + // + function showNotableTraitPopup(elem) { + if (elem === window.currentNotableElem) { + window.currentNotablePopup.style.display = ""; + window.currentNotableElem = null; + return; + } else if (window.currentNotablePopup) { + window.currentNotablePopup.style.display = ""; + } + var elemRect = elem.getBoundingClientRect(); + var containerRect = main.getBoundingClientRect(); + + var index = elem.getAttribute("data-index"); + var notableTraitContainer = document.getElementById("notable-traits"); + var notable = notableTraitContainer.children[parseInt(index)]; + + notable.style.top = (elemRect.top - containerRect.top) + "px"; + // In here, if the "i" is too much on the right, better put the popup on its left. + if (elem.offsetLeft > main.offsetWidth / 2) { + notable.style.left = ""; + notable.style.right = (main.offsetWidth - elem.offsetLeft + 2) + "px"; + } else { + notable.style.right = ""; + notable.style.left = (elem.offsetLeft + 12) + "px"; + } + notable.style.display = "block"; + window.currentNotableElem = elem; + window.currentNotablePopup = notable; + } + + onEachLazy(document.getElementsByClassName("notable-traits-tooltip"), function(e) { + e.onclick = function() { + showNotableTraitPopup(this); + }; + }); }()); (function () {