about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-09-02 04:19:27 +0200
committerGitHub <noreply@github.com>2024-09-02 04:19:27 +0200
commitc90991db1759d0da7034146755c048d8e581d73c (patch)
tree4e776e0a435b54665413dccb6e1e45c1faffd89c
parent94885bc699512cfee8560e73c2a01ee6b4b76563 (diff)
parent9855a3844bbe96d03f18541bdee3e325c35c8a34 (diff)
downloadrust-c90991db1759d0da7034146755c048d8e581d73c.tar.gz
rust-c90991db1759d0da7034146755c048d8e581d73c.zip
Rollup merge of #127474 - tesuji:foldable-inline-derefs, r=t-rustdoc
doc: Make block of inline Deref methods foldable

After:
![image](https://github.com/rust-lang/rust/assets/15225902/3e8ab320-dbf7-436f-9be0-d0ef82664663)
Before:
![image](https://github.com/rust-lang/rust/assets/15225902/f6f7635d-d4c3-437e-a2d9-147726287b05)

Fix  #127470.

Current status:
- [x] Bug when hovering over title "Methods from ...": The anchor sign $ overlaps with `[-]`: https://github.com/rust-lang/rust/pull/127474#issuecomment-2222930038
    => Fixed by https://github.com/rust-lang/rust/pull/127474#issuecomment-2228886292
-rw-r--r--src/librustdoc/html/render/mod.rs17
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css10
-rw-r--r--tests/rustdoc-gui/deref-block.goml30
-rw-r--r--tests/rustdoc-gui/src/lib2/lib.rs10
4 files changed, 63 insertions, 4 deletions
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index fc4033f8320..dc34c7844bf 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1250,6 +1250,7 @@ fn render_assoc_items_inner(
     let Some(v) = cache.impls.get(&it) else { return };
     let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
     if !non_trait.is_empty() {
+        let mut close_tags = <Vec<&str>>::with_capacity(1);
         let mut tmp_buf = Buffer::html();
         let (render_mode, id, class_html) = match what {
             AssocItemRender::All => {
@@ -1260,6 +1261,8 @@ fn render_assoc_items_inner(
                 let id =
                     cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx))));
                 let derived_id = cx.derive_id(&id);
+                tmp_buf.write_str("<details class=\"toggle big-toggle\" open><summary>");
+                close_tags.push("</details>");
                 write_impl_section_heading(
                     &mut tmp_buf,
                     &format!(
@@ -1269,6 +1272,7 @@ fn render_assoc_items_inner(
                     ),
                     &id,
                 );
+                tmp_buf.write_str("</summary>");
                 if let Some(def_id) = type_.def_id(cx.cache()) {
                     cx.deref_id_map.insert(def_id, id);
                 }
@@ -1302,6 +1306,9 @@ fn render_assoc_items_inner(
                 impls_buf.into_inner()
             )
             .unwrap();
+            for tag in close_tags.into_iter().rev() {
+                w.write_str(tag).unwrap();
+            }
         }
     }
 
@@ -1558,7 +1565,7 @@ fn render_impl(
     let cache = &shared.cache;
     let traits = &cache.traits;
     let trait_ = i.trait_did().map(|did| &traits[&did]);
-    let mut close_tags = String::new();
+    let mut close_tags = <Vec<&str>>::with_capacity(2);
 
     // For trait implementations, the `interesting` output contains all methods that have doc
     // comments, and the `boring` output contains all methods that do not. The distinction is
@@ -1870,7 +1877,7 @@ fn render_impl(
     if render_mode == RenderMode::Normal {
         let toggled = !(impl_items.is_empty() && default_impl_items.is_empty());
         if toggled {
-            close_tags.insert_str(0, "</details>");
+            close_tags.push("</details>");
             write!(
                 w,
                 "<details class=\"toggle implementors-toggle\"{}>\
@@ -1916,14 +1923,16 @@ fn render_impl(
         }
         if !default_impl_items.is_empty() || !impl_items.is_empty() {
             w.write_str("<div class=\"impl-items\">");
-            close_tags.insert_str(0, "</div>");
+            close_tags.push("</div>");
         }
     }
     if !default_impl_items.is_empty() || !impl_items.is_empty() {
         w.push_buffer(default_impl_items);
         w.push_buffer(impl_items);
     }
-    w.write_str(&close_tags);
+    for tag in close_tags.into_iter().rev() {
+        w.write_str(tag);
+    }
 }
 
 // Render the items that appear on the right side of methods, impls, and
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 28df8d3f011..1e483062289 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1852,6 +1852,11 @@ details.toggle {
 	position: relative;
 }
 
+details.big-toggle {
+	/* This makes [-] on the same line as <summary>. */
+	contain: inline-size;
+}
+
 /* The hideme class is used on summary tags that contain a span with
 	placeholder text shown only when the toggle is closed. For instance,
 	"Expand description" or "Show methods". */
@@ -1942,6 +1947,11 @@ details.toggle > summary:not(.hideme)::before {
 	left: -24px;
 }
 
+details.big-toggle > summary:not(.hideme)::before {
+	left: -34px;
+	top: 9px;
+}
+
 /* When a "hideme" summary is open and the "Expand description" or "Show
 	methods" text is hidden, we want the [-] toggle that remains to not
 	affect the layout of the items to its right. To do that, we use
diff --git a/tests/rustdoc-gui/deref-block.goml b/tests/rustdoc-gui/deref-block.goml
new file mode 100644
index 00000000000..24f612f8a6f
--- /dev/null
+++ b/tests/rustdoc-gui/deref-block.goml
@@ -0,0 +1,30 @@
+// This test ensures that several clickable items actually have the pointer cursor.
+go-to: "file://" + |DOC_PATH| + "/lib2/struct.Derefer.html"
+
+assert-text: (".big-toggle summary", "Methods from Deref<Target = str>§")
+// We ensure it doesn't go over `§`.
+assert-css: (".big-toggle summary::before", {
+    "left": "-34px",
+    "top": "9px",
+})
+// It should NOT have the same X or Y position as the other toggles.
+compare-elements-position-false: (
+    ".big-toggle summary::before",
+    ".method-toggle summary::before",
+    ["x", "y"],
+)
+
+// We now check that if we're in mobile mode, it gets back to its original X position.
+set-window-size: (600, 600)
+assert-css: (".big-toggle summary::before", {
+    "left": "-11px",
+    "top": "9px",
+})
+// It should have the same X position as the other toggles.
+compare-elements-position: (".big-toggle summary::before", ".method-toggle summary::before", ["x"])
+// But still shouldn't have the same Y position.
+compare-elements-position-false: (
+    ".big-toggle summary::before",
+    ".method-toggle summary::before",
+    ["y"],
+)
diff --git a/tests/rustdoc-gui/src/lib2/lib.rs b/tests/rustdoc-gui/src/lib2/lib.rs
index 2467c7adae1..8db754f91ce 100644
--- a/tests/rustdoc-gui/src/lib2/lib.rs
+++ b/tests/rustdoc-gui/src/lib2/lib.rs
@@ -356,3 +356,13 @@ pub mod scroll_traits {
         fn this_is_a_method_with_a_long_name_returning_something() -> String;
     }
 }
+
+pub struct Derefer(String);
+
+impl std::ops::Deref for Derefer {
+    type Target = str;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}