Rollup merge of #131906 - notriddle:notriddle/spacing, r=GuillaumeGomez

rustdoc: adjust spacing and typography in header

Fixes #131589

Preview: https://notriddle.com/rustdoc-html-demo-12/spacing/std/index.html

| Before | After |
|--|--|
| ![image](https://github.com/user-attachments/assets/b5c5132d-1e5e-402e-ba19-1dea9e70ea6f) | ![image](https://github.com/user-attachments/assets/72570b93-bb16-4553-9da7-fc4f29b98873)
| ![image](https://github.com/user-attachments/assets/264983f0-5aec-4120-8a03-f62e52d4360d) | ![image](https://github.com/user-attachments/assets/b6925945-95e6-4858-8e91-4cfd90c164f0)
| ![image](https://github.com/user-attachments/assets/df96bfe7-195d-4aaf-97f1-a45ade34cab2) | ![image](https://github.com/user-attachments/assets/c6fe2d57-bd8a-42aa-b3cf-4f635809b9b4)
| ![image](https://github.com/user-attachments/assets/7519faa5-d6b2-41ba-9d95-6000d1dd89d1) | ![image](https://github.com/user-attachments/assets/7233c2d6-82d9-4820-bb63-dc4776a34601)

First of all, we put 4px additional margin below the search box, and 4px margin below the header to balance it out.

The bigger problem we have to solve is making the lines look logically spaced. This is troublesome, because Fira Sans (the typeface we use here) wants to look good on average, and to avoid breaking, with text that uses [ascenders and descenders](https://www.w3.org/TR/css-inline-3/images/text-edge.png). If the text we're putting in happens to not have any, things look weird (strictly speaking, there’s hand-tuning here, because the Copy Path button messes with stuff, but the overall point is that there is no true, one perfect layout).

In order to play nicely with the font, I've tweaked the text to use that space. The word "Source" for the link is now capitalized, and the Since version number now uses oldstyle nums with descenders.
This commit is contained in:
Matthias Krüger 2024-10-24 10:35:39 +02:00 committed by GitHub
commit 96558580ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 53 additions and 47 deletions

View File

@ -2010,9 +2010,9 @@ fn render_rightside(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, render
); );
if let Some(link) = src_href { if let Some(link) = src_href {
if has_stability { if has_stability {
write!(rightside, " · <a class=\"src\" href=\"{link}\">source</a>") write!(rightside, " · <a class=\"src\" href=\"{link}\">Source</a>")
} else { } else {
write!(rightside, "<a class=\"src rightside\" href=\"{link}\">source</a>") write!(rightside, "<a class=\"src rightside\" href=\"{link}\">Source</a>")
} }
} }
if has_stability && has_src_ref { if has_stability && has_src_ref {

View File

@ -185,7 +185,7 @@ h1, h2, h3, h4 {
grid-template-columns: minmax(105px, 1fr) minmax(0, max-content); grid-template-columns: minmax(105px, 1fr) minmax(0, max-content);
grid-template-rows: minmax(25px, min-content) min-content min-content; grid-template-rows: minmax(25px, min-content) min-content min-content;
padding-bottom: 6px; padding-bottom: 6px;
margin-bottom: 11px; margin-bottom: 15px;
} }
.rustdoc-breadcrumbs { .rustdoc-breadcrumbs {
grid-area: main-heading-breadcrumbs; grid-area: main-heading-breadcrumbs;
@ -1004,6 +1004,7 @@ nav.sub {
display: flex; display: flex;
height: 34px; height: 34px;
flex-grow: 1; flex-grow: 1;
margin-bottom: 4px;
} }
.src nav.sub { .src nav.sub {
margin: 0 0 -10px 0; margin: 0 0 -10px 0;
@ -2253,7 +2254,12 @@ in src-script.js and main.js
/* We don't display this button on mobile devices. */ /* We don't display this button on mobile devices. */
#copy-path { #copy-path {
display: none; /* display: none; avoided as a layout hack.
When there's one line, we get an effective line-height of 34px,
because that's how big the image is, but if the header wraps,
they're packed more tightly than that. */
width: 0;
visibility: hidden;
} }
/* Text label takes up too much space at this size. */ /* Text label takes up too much space at this size. */

View File

@ -26,7 +26,7 @@
{% match src_href %} {% match src_href %}
{% when Some with (href) %} {% when Some with (href) %}
{% if !stability_since_raw.is_empty() +%} · {%+ endif %} {% if !stability_since_raw.is_empty() +%} · {%+ endif %}
<a class="src" href="{{href|safe}}">source</a> {#+ #} <a class="src" href="{{href|safe}}">Source</a> {#+ #}
{% else %} {% else %}
{% endmatch %} {% endmatch %}
</span> {# #} </span> {# #}

View File

@ -20,7 +20,7 @@ store-position: (
{"x": second_line_x, "y": second_line_y}, {"x": second_line_x, "y": second_line_y},
) )
assert: |first_line_x| != |second_line_x| && |first_line_x| == 516 && |second_line_x| == 272 assert: |first_line_x| != |second_line_x| && |first_line_x| == 516 && |second_line_x| == 272
assert: |first_line_y| != |second_line_y| && |first_line_y| == 714 && |second_line_y| == 737 assert: |first_line_y| != |second_line_y| && |first_line_y| == 718 && |second_line_y| == 741
// Now we ensure that they're not rendered on the same line. // Now we ensure that they're not rendered on the same line.
set-window-size: (1100, 800) set-window-size: (1100, 800)

View File

@ -80,8 +80,8 @@ click: ".scraped-example .button-holder .expand"
store-value: (offset_y, 4) store-value: (offset_y, 4)
// First with desktop // First with desktop
assert-position: (".scraped-example", {"y": 252}) assert-position: (".scraped-example", {"y": 256})
assert-position: (".scraped-example .prev", {"y": 252 + |offset_y|}) assert-position: (".scraped-example .prev", {"y": 256 + |offset_y|})
// Gradient background should be at the top of the code block. // Gradient background should be at the top of the code block.
assert-css: (".scraped-example .example-wrap::before", {"top": "0px"}) assert-css: (".scraped-example .example-wrap::before", {"top": "0px"})
@ -90,8 +90,8 @@ assert-css: (".scraped-example .example-wrap::after", {"bottom": "0px"})
// Then with mobile // Then with mobile
set-window-size: (600, 600) set-window-size: (600, 600)
store-size: (".scraped-example .scraped-example-title", {"height": title_height}) store-size: (".scraped-example .scraped-example-title", {"height": title_height})
assert-position: (".scraped-example", {"y": 287}) assert-position: (".scraped-example", {"y": 291})
assert-position: (".scraped-example .prev", {"y": 287 + |offset_y| + |title_height|}) assert-position: (".scraped-example .prev", {"y": 291 + |offset_y| + |title_height|})
define-function: ( define-function: (
"check_title_and_code_position", "check_title_and_code_position",

View File

@ -141,7 +141,7 @@ click: "#sidebar-button"
wait-for-css: (".src .sidebar > *", {"visibility": "hidden"}) wait-for-css: (".src .sidebar > *", {"visibility": "hidden"})
// We scroll to line 117 to change the scroll position. // We scroll to line 117 to change the scroll position.
scroll-to: '//*[@id="117"]' scroll-to: '//*[@id="117"]'
store-value: (y_offset, "2570") store-value: (y_offset, "2578")
assert-window-property: {"pageYOffset": |y_offset|} assert-window-property: {"pageYOffset": |y_offset|}
// Expanding the sidebar... // Expanding the sidebar...
click: "#sidebar-button" click: "#sidebar-button"

View File

@ -8,13 +8,13 @@ set-window-size: (600, 800)
assert-property: ("html", {"scrollTop": "0"}) assert-property: ("html", {"scrollTop": "0"})
click: '//a[text() = "barbar" and @href="#5-7"]' click: '//a[text() = "barbar" and @href="#5-7"]'
assert-property: ("html", {"scrollTop": "200"}) assert-property: ("html", {"scrollTop": "208"})
click: '//a[text() = "bar" and @href="#28-36"]' click: '//a[text() = "bar" and @href="#28-36"]'
assert-property: ("html", {"scrollTop": "231"}) assert-property: ("html", {"scrollTop": "239"})
click: '//a[normalize-space() = "sub_fn" and @href="#2-4"]' click: '//a[normalize-space() = "sub_fn" and @href="#2-4"]'
assert-property: ("html", {"scrollTop": "128"}) assert-property: ("html", {"scrollTop": "136"})
// We now check that clicking on lines doesn't change the scroll // We now check that clicking on lines doesn't change the scroll
// Extra information: the "sub_fn" function header is on line 1. // Extra information: the "sub_fn" function header is on line 1.
click: '//*[@id="6"]' click: '//*[@id="6"]'
assert-property: ("html", {"scrollTop": "128"}) assert-property: ("html", {"scrollTop": "136"})

View File

@ -89,7 +89,7 @@ assert-css: (".src-line-numbers", {"text-align": "right"})
// do anything (and certainly not add a `#NaN` to the URL!). // do anything (and certainly not add a `#NaN` to the URL!).
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html" go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
// We use this assert-position to know where we will click. // We use this assert-position to know where we will click.
assert-position: ("//*[@id='1']", {"x": 88, "y": 163}) assert-position: ("//*[@id='1']", {"x": 88, "y": 171})
// We click on the left of the "1" anchor but still in the "src-line-number" `<pre>`. // We click on the left of the "1" anchor but still in the "src-line-number" `<pre>`.
click: (163, 77) click: (163, 77)
assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH) assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH)
@ -165,7 +165,7 @@ assert-css: ("nav.sub", {"flex-direction": "row"})
// offsetTop[nav.sub form] = offsetTop[#main-content] - offsetHeight[nav.sub form] - offsetTop[nav.sub form] // offsetTop[nav.sub form] = offsetTop[#main-content] - offsetHeight[nav.sub form] - offsetTop[nav.sub form]
assert-position: ("nav.sub form", {"y": 15}) assert-position: ("nav.sub form", {"y": 15})
assert-property: ("nav.sub form", {"offsetHeight": 34}) assert-property: ("nav.sub form", {"offsetHeight": 34})
assert-position: ("h1", {"y": 64}) assert-position: ("h1", {"y": 68})
// 15 = 64 - 34 - 15 // 15 = 64 - 34 - 15
// Now do the same check on moderately-sized, tablet mobile. // Now do the same check on moderately-sized, tablet mobile.
@ -173,7 +173,7 @@ set-window-size: (700, 700)
assert-css: ("nav.sub", {"flex-direction": "row"}) assert-css: ("nav.sub", {"flex-direction": "row"})
assert-position: ("nav.sub form", {"y": 8}) assert-position: ("nav.sub form", {"y": 8})
assert-property: ("nav.sub form", {"offsetHeight": 34}) assert-property: ("nav.sub form", {"offsetHeight": 34})
assert-position: ("h1", {"y": 50}) assert-position: ("h1", {"y": 54})
// 8 = 50 - 34 - 8 // 8 = 50 - 34 - 8
// Check the sidebar directory entries have a marker and spacing (tablet). // Check the sidebar directory entries have a marker and spacing (tablet).

View File

@ -1 +1 @@
<section id="associatedconstant.YOLO" class="method"><a class="src rightside" href="../src/foo/anchors.rs.html#16">source</a><h4 class="code-header">const <a href="#associatedconstant.YOLO" class="constant">YOLO</a>: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></section> <section id="associatedconstant.YOLO" class="method"><a class="src rightside" href="../src/foo/anchors.rs.html#16">Source</a><h4 class="code-header">const <a href="#associatedconstant.YOLO" class="constant">YOLO</a>: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></section>

View File

@ -1 +1 @@
<section id="associatedconstant.X" class="associatedconstant"><a class="src rightside" href="../src/foo/anchors.rs.html#42">source</a><h4 class="code-header">pub const <a href="#associatedconstant.X" class="constant">X</a>: <a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a> = 0i32</h4></section> <section id="associatedconstant.X" class="associatedconstant"><a class="src rightside" href="../src/foo/anchors.rs.html#42">Source</a><h4 class="code-header">pub const <a href="#associatedconstant.X" class="constant">X</a>: <a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a> = 0i32</h4></section>

View File

@ -1 +1 @@
<section id="method.new" class="method"><a class="src rightside" href="../src/foo/anchors.rs.html#48">source</a><h4 class="code-header">pub fn <a href="#method.new" class="fn">new</a>() -&gt; Self</h4></section> <section id="method.new" class="method"><a class="src rightside" href="../src/foo/anchors.rs.html#48">Source</a><h4 class="code-header">pub fn <a href="#method.new" class="fn">new</a>() -&gt; Self</h4></section>

View File

@ -1 +1 @@
<section id="method.bar" class="method"><a class="src rightside" href="../src/foo/anchors.rs.html#23">source</a><h4 class="code-header">fn <a href="#method.bar" class="fn">bar</a>()</h4></section> <section id="method.bar" class="method"><a class="src rightside" href="../src/foo/anchors.rs.html#23">Source</a><h4 class="code-header">fn <a href="#method.bar" class="fn">bar</a>()</h4></section>

View File

@ -1 +1 @@
<section id="tymethod.foo" class="method"><a class="src rightside" href="../src/foo/anchors.rs.html#20">source</a><h4 class="code-header">fn <a href="#tymethod.foo" class="fn">foo</a>()</h4></section> <section id="tymethod.foo" class="method"><a class="src rightside" href="../src/foo/anchors.rs.html#20">Source</a><h4 class="code-header">fn <a href="#tymethod.foo" class="fn">foo</a>()</h4></section>

View File

@ -1 +1 @@
<section id="associatedtype.T" class="method"><a class="src rightside" href="../src/foo/anchors.rs.html#13">source</a><h4 class="code-header">type <a href="#associatedtype.T" class="associatedtype">T</a></h4></section> <section id="associatedtype.T" class="method"><a class="src rightside" href="../src/foo/anchors.rs.html#13">Source</a><h4 class="code-header">type <a href="#associatedtype.T" class="associatedtype">T</a></h4></section>

View File

@ -1 +1 @@
<section id="associatedtype.Y" class="associatedtype"><a class="src rightside" href="../src/foo/anchors.rs.html#45">source</a><h4 class="code-header">pub type <a href="#associatedtype.Y" class="associatedtype">Y</a> = <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></section> <section id="associatedtype.Y" class="associatedtype"><a class="src rightside" href="../src/foo/anchors.rs.html#45">Source</a><h4 class="code-header">pub type <a href="#associatedtype.Y" class="associatedtype">Y</a> = <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></section>

View File

@ -8,7 +8,7 @@
pub struct Bar; pub struct Bar;
impl Bar { impl Bar {
//@ has - '//*[@id="implementations-list"]//*[@id="associatedtype.Y"]/a' 'source' //@ has - '//*[@id="implementations-list"]//*[@id="associatedtype.Y"]/a' 'Source'
//@ has - '//*[@id="implementations-list"]//*[@id="associatedtype.Y"]/a/@href' \ //@ has - '//*[@id="implementations-list"]//*[@id="associatedtype.Y"]/a/@href' \
// '../src/foo/assoc-type-source-link.rs.html#14' // '../src/foo/assoc-type-source-link.rs.html#14'
pub type Y = u8; pub type Y = u8;
@ -19,7 +19,7 @@ pub trait Foo {
} }
impl Foo for Bar { impl Foo for Bar {
//@ has - '//*[@id="trait-implementations-list"]//*[@id="associatedtype.Z"]/a' 'source' //@ has - '//*[@id="trait-implementations-list"]//*[@id="associatedtype.Z"]/a' 'Source'
//@ has - '//*[@id="trait-implementations-list"]//*[@id="associatedtype.Z"]/a/@href' \ //@ has - '//*[@id="trait-implementations-list"]//*[@id="associatedtype.Z"]/a/@href' \
// '../src/foo/assoc-type-source-link.rs.html#25' // '../src/foo/assoc-type-source-link.rs.html#25'
type Z = u8; type Z = u8;

View File

@ -2,5 +2,5 @@
// This test ensures that the [src] link is present on traits items. // This test ensures that the [src] link is present on traits items.
//@ has foo/trait.Iterator.html '//*[@id="method.zip"]//a[@class="src"]' "source" //@ has foo/trait.Iterator.html '//*[@id="method.zip"]//a[@class="src"]' "Source"
pub use std::iter::Iterator; pub use std::iter::Iterator;

View File

@ -5,8 +5,8 @@
#[macro_use] #[macro_use]
extern crate external_macro_src; extern crate external_macro_src;
//@ has foo/index.html '//a[@href="../src/foo/external-macro-src.rs.html#3-12"]' 'source' //@ has foo/index.html '//a[@href="../src/foo/external-macro-src.rs.html#3-12"]' 'Source'
//@ has foo/struct.Foo.html //@ has foo/struct.Foo.html
//@ has - '//a[@href="../src/foo/external-macro-src.rs.html#12"]' 'source' //@ has - '//a[@href="../src/foo/external-macro-src.rs.html#12"]' 'Source'
make_foo!(); make_foo!();

View File

@ -3,23 +3,23 @@
#![feature(staged_api)] #![feature(staged_api)]
//@ has foo/trait.Bar.html //@ has foo/trait.Bar.html
//@ has - '//div[@class="main-heading"]/*[@class="sub-heading"]' '1.0.0 · source' //@ has - '//div[@class="main-heading"]/*[@class="sub-heading"]' '1.0.0 · Source'
#[stable(feature = "bar", since = "1.0")] #[stable(feature = "bar", since = "1.0")]
pub trait Bar { pub trait Bar {
//@ has - '//*[@id="tymethod.foo"]/*[@class="rightside"]' '3.0.0 · source' //@ has - '//*[@id="tymethod.foo"]/*[@class="rightside"]' '3.0.0 · Source'
#[stable(feature = "foobar", since = "3.0")] #[stable(feature = "foobar", since = "3.0")]
fn foo(); fn foo();
} }
//@ has - '//div[@id="implementors-list"]//*[@class="rightside"]' '4.0.0 · source' //@ has - '//div[@id="implementors-list"]//*[@class="rightside"]' '4.0.0 · Source'
//@ has foo/struct.Foo.html //@ has foo/struct.Foo.html
//@ has - '//div[@class="main-heading"]/*[@class="sub-heading"]' '1.0.0 · source' //@ has - '//div[@class="main-heading"]/*[@class="sub-heading"]' '1.0.0 · Source'
#[stable(feature = "baz", since = "1.0")] #[stable(feature = "baz", since = "1.0")]
pub struct Foo; pub struct Foo;
impl Foo { impl Foo {
//@ has - '//*[@id="method.foofoo"]/*[@class="rightside"]' '3.0.0 · source' //@ has - '//*[@id="method.foofoo"]/*[@class="rightside"]' '3.0.0 · Source'
#[stable(feature = "foobar", since = "3.0")] #[stable(feature = "foobar", since = "3.0")]
pub fn foofoo() {} pub fn foofoo() {}
} }

View File

@ -10,5 +10,5 @@
extern crate issue_26606_macro; extern crate issue_26606_macro;
//@ has issue_26606/constant.FOO.html //@ has issue_26606/constant.FOO.html
//@ has - '//a[@href="../src/issue_26606/src-link-external-macro-26606.rs.html#14"]' 'source' //@ has - '//a[@href="../src/issue_26606/src-link-external-macro-26606.rs.html#14"]' 'Source'
make_item!(FOO); make_item!(FOO);

View File

@ -2,11 +2,11 @@
//@ has foo/struct.Unsized.html //@ has foo/struct.Unsized.html
//@ has - '//*[@id="impl-Sized-for-Unsized"]/h3[@class="code-header"]' 'impl !Sized for Unsized' //@ has - '//*[@id="impl-Sized-for-Unsized"]/h3[@class="code-header"]' 'impl !Sized for Unsized'
//@ !has - '//*[@id="impl-Sized-for-Unsized"]//a[@class="src"]' 'source' //@ !has - '//*[@id="impl-Sized-for-Unsized"]//a[@class="src"]' 'Source'
//@ has - '//*[@id="impl-Sync-for-Unsized"]/h3[@class="code-header"]' 'impl Sync for Unsized' //@ has - '//*[@id="impl-Sync-for-Unsized"]/h3[@class="code-header"]' 'impl Sync for Unsized'
//@ !has - '//*[@id="impl-Sync-for-Unsized"]//a[@class="src"]' 'source' //@ !has - '//*[@id="impl-Sync-for-Unsized"]//a[@class="src"]' 'Source'
//@ has - '//*[@id="impl-Any-for-T"]/h3[@class="code-header"]' 'impl<T> Any for T' //@ has - '//*[@id="impl-Any-for-T"]/h3[@class="code-header"]' 'impl<T> Any for T'
//@ has - '//*[@id="impl-Any-for-T"]//a[@class="src rightside"]' 'source' //@ has - '//*[@id="impl-Any-for-T"]//a[@class="src rightside"]' 'Source'
pub struct Unsized { pub struct Unsized {
data: [u8], data: [u8],
} }

View File

@ -1,6 +1,6 @@
#![crate_name = "foo"] #![crate_name = "foo"]
//@ has foo/index.html '//a[@href="../src/foo/thread-local-src.rs.html#1-6"]' 'source' //@ has foo/index.html '//a[@href="../src/foo/thread-local-src.rs.html#1-6"]' 'Source'
//@ has foo/constant.FOO.html '//a[@href="../src/foo/thread-local-src.rs.html#6"]' 'source' //@ has foo/constant.FOO.html '//a[@href="../src/foo/thread-local-src.rs.html#6"]' 'Source'
thread_local!(pub static FOO: bool = false); thread_local!(pub static FOO: bool = false);

View File

@ -1,26 +1,26 @@
#![crate_name = "quix"] #![crate_name = "quix"]
pub trait Foo { pub trait Foo {
//@ has quix/trait.Foo.html '//a[@href="../src/quix/trait-src-link.rs.html#4"]' 'source' //@ has quix/trait.Foo.html '//a[@href="../src/quix/trait-src-link.rs.html#4"]' 'Source'
fn required(); fn required();
//@ has quix/trait.Foo.html '//a[@href="../src/quix/trait-src-link.rs.html#7"]' 'source' //@ has quix/trait.Foo.html '//a[@href="../src/quix/trait-src-link.rs.html#7"]' 'Source'
fn provided() {} fn provided() {}
} }
pub struct Bar; pub struct Bar;
impl Foo for Bar { impl Foo for Bar {
//@ has quix/struct.Bar.html '//a[@href="../src/quix/trait-src-link.rs.html#14"]' 'source' //@ has quix/struct.Bar.html '//a[@href="../src/quix/trait-src-link.rs.html#14"]' 'Source'
fn required() {} fn required() {}
//@ has quix/struct.Bar.html '//a[@href="../src/quix/trait-src-link.rs.html#7"]' 'source' //@ has quix/struct.Bar.html '//a[@href="../src/quix/trait-src-link.rs.html#7"]' 'Source'
} }
pub struct Baz; pub struct Baz;
impl Foo for Baz { impl Foo for Baz {
//@ has quix/struct.Baz.html '//a[@href="../src/quix/trait-src-link.rs.html#22"]' 'source' //@ has quix/struct.Baz.html '//a[@href="../src/quix/trait-src-link.rs.html#22"]' 'Source'
fn required() {} fn required() {}
//@ has quix/struct.Baz.html '//a[@href="../src/quix/trait-src-link.rs.html#25"]' 'source' //@ has quix/struct.Baz.html '//a[@href="../src/quix/trait-src-link.rs.html#25"]' 'Source'
fn provided() {} fn provided() {}
} }