about summary refs log tree commit diff
path: root/src/librustdoc/html
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2020-07-16 11:18:55 -0700
committerGitHub <noreply@github.com>2020-07-16 11:18:55 -0700
commitfc098170ce8934e1887ec7978c5b8d198c140a2a (patch)
tree46e4cdabeb12a1cb268e8b19c03d224c8777960b /src/librustdoc/html
parent61fccf05f90b1a99a62ccd811152c4eeec57fba3 (diff)
parentc621a54eeb71248927dff8ac0c76f279cf756f28 (diff)
downloadrust-fc098170ce8934e1887ec7978c5b8d198c140a2a.tar.gz
rust-fc098170ce8934e1887ec7978c5b8d198c140a2a.zip
Rollup merge of #74370 - Manishearth:re-spotlight, r=GuillaumeGomez
Reintroduce spotlight / "important traits" feature

(Reopened version of https://github.com/rust-lang/rust/pull/74111 because Github is broken, see discussion there)

Fixes https://github.com/rust-lang/rust/issues/73785

This PR reintroduces the "spotlight" ("important traits") feature.

A couple changes have been made:

As there were concerns about its visibility, it has been moved to be next to the return type, as opposed to being on the side.

It also no longer produces a modal, it shows the traits on hover, and it can be clicked on to pin the hover bubble.

![image](https://user-images.githubusercontent.com/1617736/86674555-a82d2600-bfad-11ea-9a4a-a1a9ffd66ae5.png)

![image](https://user-images.githubusercontent.com/1617736/86674533-a1061800-bfad-11ea-9e8a-c62ad86ed0d7.png)

It also works fine on mobile:

![image](https://user-images.githubusercontent.com/1617736/86674638-bda25000-bfad-11ea-8d8d-1798b608923e.png)
Diffstat (limited to 'src/librustdoc/html')
-rw-r--r--src/librustdoc/html/format.rs12
-rw-r--r--src/librustdoc/html/render.rs69
-rw-r--r--src/librustdoc/html/static/main.js7
-rw-r--r--src/librustdoc/html/static/rustdoc.css74
-rw-r--r--src/librustdoc/html/static/themes/ayu.css5
-rw-r--r--src/librustdoc/html/static/themes/dark.css5
-rw-r--r--src/librustdoc/html/static/themes/light.css5
7 files changed, 163 insertions, 14 deletions
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index a453a8b3dcb..0d8284029af 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -63,10 +63,22 @@ impl Buffer {
         Buffer { for_html: false, buffer: String::new() }
     }
 
+    crate fn is_empty(&self) -> bool {
+        self.buffer.is_empty()
+    }
+
     crate fn into_inner(self) -> String {
         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);
+    }
+
     // Intended for consumption by write! and writeln! (std::fmt) but without
     // the fmt::Result return type imposed by fmt::Write (and avoiding the trait
     // import).
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index f8f950bccb1..31e35125dac 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -2415,7 +2415,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
     write!(
         w,
         "{vis}{constness}{asyncness}{unsafety}{abi}fn \
-           {name}{generics}{decl}{where_clause}</pre>",
+           {name}{generics}{decl}{spotlight}{where_clause}</pre>",
         vis = it.visibility.print_with_space(),
         constness = f.header.constness.print_with_space(),
         asyncness = f.header.asyncness.print_with_space(),
@@ -2425,7 +2425,8 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
         generics = f.generics.print(),
         where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true },
         decl = Function { decl: &f.decl, header_len, indent: 0, asyncness: f.header.asyncness }
-            .print()
+            .print(),
+        spotlight = spotlight_decl(&f.decl),
     );
     document(w, cx, it)
 }
@@ -2612,7 +2613,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
         let name = m.name.as_ref().unwrap();
         let item_type = m.type_();
         let id = cx.derive_id(format!("{}.{}", item_type, name));
-        write!(w, "<h3 id='{id}' class='method'><code>", id = id);
+        write!(w, "<h3 id='{id}' class='method'><code>", id = id,);
         render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl);
         write!(w, "</code>");
         render_stability_since(w, m, t);
@@ -2926,7 +2927,7 @@ fn render_assoc_item(
         write!(
             w,
             "{}{}{}{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
-                   {generics}{decl}{where_clause}",
+                   {generics}{decl}{spotlight}{where_clause}",
             if parent == ItemType::Trait { "    " } else { "" },
             meth.visibility.print_with_space(),
             header.constness.print_with_space(),
@@ -2938,6 +2939,7 @@ fn render_assoc_item(
             name = name,
             generics = g.print(),
             decl = Function { decl: d, header_len, indent, asyncness: header.asyncness }.print(),
+            spotlight = spotlight_decl(&d),
             where_clause = WhereClause { gens: g, indent, end_newline }
         )
     }
@@ -3559,6 +3561,62 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool {
     }
 }
 
+fn spotlight_decl(decl: &clean::FnDecl) -> String {
+    let mut out = Buffer::html();
+    let mut trait_ = String::new();
+
+    if let Some(did) = decl.output.def_id() {
+        let c = cache();
+        if let Some(impls) = c.impls.get(&did) {
+            for i in impls {
+                let impl_ = i.inner_impl();
+                if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) {
+                    if out.is_empty() {
+                        out.push_str(&format!(
+                            "<h3 class=\"important\">Important traits for {}</h3>\
+                                      <code class=\"content\">",
+                            impl_.for_.print()
+                        ));
+                        trait_.push_str(&impl_.for_.print().to_string());
+                    }
+
+                    //use the "where" class here to make it small
+                    out.push_str(&format!(
+                        "<span class=\"where fmt-newline\">{}</span>",
+                        impl_.print()
+                    ));
+                    let t_did = impl_.trait_.def_id().unwrap();
+                    for it in &impl_.items {
+                        if let clean::TypedefItem(ref tydef, _) = it.inner {
+                            out.push_str("<span class=\"where fmt-newline\">    ");
+                            assoc_type(
+                                &mut out,
+                                it,
+                                &[],
+                                Some(&tydef.type_),
+                                AssocItemLink::GotoSource(t_did, &FxHashSet::default()),
+                                "",
+                            );
+                            out.push_str(";</span>");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if !out.is_empty() {
+        out.insert_str(
+            0,
+            "<span class=\"important-traits\"><span class=\"important-traits-tooltip\">ⓘ<div class='important-traits-tooltiptext'><span class=\"docblock\">"
+
+        );
+        out.push_str("</code></span></div></span></span>");
+    }
+
+    out.into_inner()
+}
+
 fn render_impl(
     w: &mut Buffer,
     cx: &Context,
@@ -3670,7 +3728,8 @@ fn render_impl(
                 // Only render when the method is not static or we allow static methods
                 if render_method_item {
                     let id = cx.derive_id(format!("{}.{}", item_type, name));
-                    write!(w, "<h4 id='{}' class=\"{}{}\"><code>", id, item_type, extra_class);
+                    write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class);
+                    write!(w, "<code>");
                     render_assoc_item(w, item, link.anchor(&id), ItemType::Impl);
                     write!(w, "</code>");
                     render_stability_since_raw(w, item.stable_since(), outer_version);
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 336c691ac1c..082f9cca064 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -2636,6 +2636,13 @@ function defocusSearchBar() {
         });
     }());
 
+    onEachLazy(document.getElementsByClassName("important-traits"), function(e) {
+        e.onclick = function() {
+            this.getElementsByClassName('important-traits-tooltiptext')[0]
+                .classList.toggle("force-tooltip");
+        };
+    });
+
     // In the search display, allows to switch between tabs.
     function printTab(nb) {
         if (nb === 0 || nb === 1 || nb === 2) {
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 15a0c76ceea..f5551446bf2 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -146,9 +146,12 @@ code, pre, a.test-arrow {
 	border-radius: 3px;
 	padding: 0 0.1em;
 }
-.docblock pre code, .docblock-short pre code {
+.docblock pre code, .docblock-short pre code, .docblock code.spotlight {
 	padding: 0;
 }
+.docblock code.spotlight :last-child {
+	padding-bottom: 0.6em;
+}
 pre {
 	padding: 14px;
 }
@@ -523,7 +526,7 @@ h4 > code, h3 > code, .invisible > code {
 	font-size: 0.8em;
 }
 
-.content .methods > div {
+.content .methods > div:not(.important-traits) {
 	margin-left: 40px;
 	margin-bottom: 15px;
 }
@@ -1079,10 +1082,6 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
 	font-size: 16px;
 }
 
-.tooltip:hover .tooltiptext {
-	display: inline;
-}
-
 .tooltip .tooltiptext::after {
 	content: " ";
 	position: absolute;
@@ -1098,13 +1097,52 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
 	font-size: 20px;
 }
 
-.tooltip .tooltiptext {
+.important-traits-tooltip {
+	display: inline-block;
+	cursor: pointer;
+}
+
+.important-traits:hover .important-traits-tooltiptext,
+.important-traits .important-traits-tooltiptext.force-tooltip {
+	display: inline-block;
+}
+
+.important-traits .important-traits-tooltiptext {
+	display: none;
+	padding: 5px 3px 3px 3px;
+	border-radius: 6px;
+	margin-left: 5px;
+	z-index: 10;
+	font-size: 16px;
+	cursor: default;
+	position: absolute;
 	border: 1px solid;
-	font-weight: normal;
 }
 
-pre.rust {
+.important-traits-tooltip::after {
+	/* The margin on the tooltip does not capture hover events,
+	   this extends the area of hover enough so that mouse hover is not
+	   lost when moving the mouse to the tooltip */
+    content: "\00a0\00a0\00a0";
+}
+
+.important-traits .important, .important-traits .docblock {
+	margin: 0;
+}
+
+.important-traits .docblock code.content{
+    margin: 0;
+    padding: 0;
+    font-size: 20px;
+}
+
+/* Example code has the "Run" button that
+   needs to be positioned relative to the pre */
+pre.rust.rust-example-rendered {
 	position: relative;
+}
+
+pre.rust {
 	tab-size: 4;
 	-moz-tab-size: 4;
 }
@@ -1144,6 +1182,18 @@ pre.rust {
 	font-size: 16px;
 }
 
+.important-traits {
+	cursor: pointer;
+	z-index: 2;
+	margin-left: 5px;
+}
+
+h4 > .important-traits {
+	position: absolute;
+	left: -44px;
+	top: 2px;
+}
+
 #all-types {
 	text-align: center;
 	border: 1px solid;
@@ -1370,6 +1420,12 @@ pre.rust {
 		z-index: 1;
 	}
 
+	h4 > .important-traits {
+		position: absolute;
+		left: -22px;
+		top: 24px;
+	}
+
 	#titles > div > div.count {
 		float: left;
 		width: 100%;
diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css
index bc21c28750f..b436997da58 100644
--- a/src/librustdoc/html/static/themes/ayu.css
+++ b/src/librustdoc/html/static/themes/ayu.css
@@ -394,6 +394,11 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	border-color: transparent #314559 transparent transparent;
 }
 
+.important-traits-tooltiptext {
+    background-color: #314559;
+    border-color: #5c6773;
+}
+
 #titles > div.selected {
     background-color: #141920 !important;
 	border-bottom: 1px solid #ffb44c !important;
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index 41dcb5c2450..f4ca67f8540 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -337,6 +337,11 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	border-color: transparent black transparent transparent;
 }
 
+.important-traits-tooltiptext {
+	background-color: #111;
+	border-color: #777;
+}
+
 #titles > div:not(.selected) {
 	background-color: #252525;
 	border-top-color: #252525;
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index 386fe2398e6..b5a0ba4775c 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -331,6 +331,11 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	border-color: transparent black transparent transparent;
 }
 
+.important-traits-tooltiptext {
+	background-color: #eee;
+	border-color: #999;
+}
+
 #titles > div:not(.selected) {
 	background-color: #e6e6e6;
 	border-top-color: #e6e6e6;