From 28ee5da4b7595465633e5852e0d5d1632fec02ae Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 18 Sep 2023 11:59:49 -0700 Subject: [PATCH 1/9] rustdoc: show crate name beside small logo This commit changes the layout to something a bit less "look at my logo!!!111" gigantic, and makes it clearer where clicking the logo will actually take you. It also means the crate name is persistently at the top of the sidebar, even when in a sub-item page, and clicking that name takes you back to the root. | | Short crate name | Long crate name | |---------|------------------|-----------------| | Root | ![short-root] | ![long-root] | Subpage | ![short-subpage] | ![long-subpage] [short-root]: https://github.com/rust-lang/rust/assets/1593513/fe2ce102-d4b8-44e6-9f7b-68636a907f56 [short-subpage]: https://github.com/rust-lang/rust/assets/1593513/29501663-56c0-4151-b7de-d2637e167125 [long-root]: https://github.com/rust-lang/rust/assets/1593513/f6a385c0-b4c5-4a9c-954b-21b38de4192f [long-subpage]: https://github.com/rust-lang/rust/assets/1593513/97ec47b4-61bf-4ebe-b461-0d2187b8c6ca https://notriddle.com/rustdoc-html-demo-4/logo-lockup/image/index.html https://notriddle.com/rustdoc-html-demo-4/logo-lockup/crossbeam_channel/index.html https://notriddle.com/rustdoc-html-demo-4/logo-lockup/adler/struct.Adler32.html https://notriddle.com/rustdoc-html-demo-4/logo-lockup/crossbeam_channel/struct.Sender.html This improves visual information density (the construct with the logo and crate name is *shorter* than the logo on its own, because it's not square) and navigation clarity (we can now see what clicking the Rust logo does, specifically). Compare this with the layout at [Phoenix's Hexdocs] (which is what this proposal is closely based on), the old proposal on [Internals Discourse] (which always says "Rust standard library" in the sidebar, but doesn't do the side-by-side layout). [Phoenix's Hexdocs]: https://hexdocs.pm/phoenix/1.7.7/overview.html [Internals Discourse]: https://internals.rust-lang.org/t/poc-of-a-new-design-for-the-generated-rustdoc/11018 In newer versions of rustdoc, the crate name and version are always shown in the sidebar, even in subpages. Clicking the crate name does the same thing clicking the logo always did: return you to the crate root. While this actually takes up less screen real estate than the old layout on desktop, it takes up more HTML. It's also a bit more visually complex. I could do what the Internals POC did and keep the vertically stacked layout all the time, instead of doing a horizontal stack where possible. It would take up more screen real estate, though. This design is lifted almost verbatim from Hexdocs. It seems to work for them. [`opentelemetry_process_propagator`], for example, has a long application name. [`opentelemetry_process_propagator`]: https://hexdocs.pm/opentelemetry_process_propagator/OpentelemetryProcessPropagator.html Has anyone written the rationale on why the Rust logo shows up on projects that aren't the standard library? If we turned it off on non-standard crates by default, it would line wrap crate names a lot less often. Or maybe we should encourage crate authors to include their own logo more often? It certainly helps give people a better sense of "place." I'm not sure of anything that directly follows up this one. Plenty of other changes could be made to improve the layout, like * coming up with a less cluttered way to do disclosure (there's a lot of `[-]` on the page) * doing a better job of separating lateral navigation (vec::Vec links to vec::IntoIter) and the table of contents (vec::Vec links to vec::Vec::new) * giving readers more control of how much rustdoc hows them, and giving doc authors more control of how much it generates * better search that reduces the need to browse But those are mostly orthogonal, not future possibilities unlocked by this change. --- src/librustdoc/html/layout.rs | 1 + src/librustdoc/html/render/context.rs | 6 +-- src/librustdoc/html/render/sidebar.rs | 9 ++-- src/librustdoc/html/static/css/rustdoc.css | 57 +++++++++++++++++----- src/librustdoc/html/static/js/main.js | 8 ++- src/librustdoc/html/templates/page.html | 22 ++++++--- src/librustdoc/html/templates/sidebar.html | 3 -- tests/rustdoc-gui/huge-logo.goml | 4 +- tests/rustdoc-gui/sidebar-mobile.goml | 2 +- tests/rustdoc-gui/sidebar.goml | 24 +++++---- tests/rustdoc/crate-version-escape.rs | 2 +- tests/rustdoc/crate-version.rs | 2 +- tests/rustdoc/titles.rs | 3 +- 13 files changed, 95 insertions(+), 48 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 8c5871d9126..25ca67db649 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -17,6 +17,7 @@ pub(crate) struct Layout { pub(crate) external_html: ExternalHtml, pub(crate) default_settings: FxHashMap, pub(crate) krate: String, + pub(crate) krate_version: String, /// The given user css file which allow to customize the generated /// documentation theme. pub(crate) css_file_extension: Option, diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 97714afaa45..62c7dbe78ec 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -534,6 +534,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { external_html, default_settings, krate: krate.name(tcx).to_string(), + krate_version: cache.crate_version.as_deref().unwrap_or_default().to_string(), css_file_extension: extension_css, scrape_examples_extension: !call_locations.is_empty(), }; @@ -669,10 +670,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { let blocks = sidebar_module_like(all.item_sections()); let bar = Sidebar { - title_prefix: "Crate ", - title: crate_name.as_str(), + title_prefix: "", + title: "", is_crate: false, - version: "", blocks: vec![blocks], path: String::new(), }; diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 76f63c6f63e..417c572fd77 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -19,7 +19,6 @@ pub(super) struct Sidebar<'a> { pub(super) title_prefix: &'static str, pub(super) title: &'a str, pub(super) is_crate: bool, - pub(super) version: &'a str, pub(super) blocks: Vec>, pub(super) path: String, } @@ -99,12 +98,12 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf || it.is_primitive() || it.is_union() || it.is_enum() - || it.is_mod() + // crate title is displayed as part of logo lockup + || (it.is_mod() && !it.is_crate()) || it.is_type_alias() { ( match *it.kind { - clean::ModuleItem(..) if it.is_crate() => "Crate ", clean::ModuleItem(..) => "Module ", _ => "", }, @@ -113,14 +112,12 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf } else { ("", "") }; - let version = - if it.is_crate() { cx.cache().crate_version.as_deref().unwrap_or_default() } else { "" }; let path: String = if !it.is_mod() { cx.current.iter().map(|s| s.as_str()).intersperse("::").collect() } else { "".into() }; - let sidebar = Sidebar { title_prefix, title, is_crate: it.is_crate(), version, blocks, path }; + let sidebar = Sidebar { title_prefix, title, is_crate: it.is_crate(), blocks, path }; sidebar.render_into(buffer).unwrap(); } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 47f9e650281..6a6747affb2 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -461,19 +461,9 @@ img { display: none !important; } -.sidebar .logo-container { - margin-top: 10px; - margin-bottom: 10px; - text-align: center; -} - -.version { - overflow-wrap: break-word; -} - .logo-container > img { - height: 100px; - width: 100px; + height: 48px; + width: 48px; } ul.block, .block li { @@ -510,6 +500,8 @@ ul.block, .block li { color: var(--sidebar-link-color); } .sidebar .current, +.sidebar .current a, +.sidebar-crate a.logo-container:hover + h2 a, .sidebar a:hover:not(.logo-container) { background-color: var(--sidebar-current-link-background-color); } @@ -524,6 +516,47 @@ ul.block, .block li { overflow: hidden; } +.sidebar-crate { + display: flex; + align-items: center; + justify-content: center; + margin: 0 32px; + column-gap: 32px; + flex-wrap: wrap; +} + +.sidebar-crate h2 { + flex-grow: 1; + /* This setup with the margins and row-gap is designed to make flex-wrap + work the way we want. If they're in the side-by-side lockup, there + should be a 16px margin to the left of the logo (visually the same as + the 24px one on everything else, which are not giant circles) and 8px + between it and the crate's name and version. When they're line wrapped, + the logo needs to have the same margin on both sides of itself (to + center properly) and the crate name and version need 24px on their + left margin. */ + margin: 0 -8px; +} + +.sidebar-crate .logo-container { + margin: 10px -16px; + text-align: center; +} + +.sidebar-crate h2 a { + display: block; + margin-left: -0.25rem; + padding-left: 0.25rem; + margin-right: -24px; +} + +.sidebar-crate h2 .version { + display: block; + font-weight: normal; + font-size: 1rem; + overflow-wrap: break-word; +} + .mobile-topbar { display: none; } diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index eb256455b08..5e852af2196 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -51,9 +51,13 @@ function setMobileTopbar() { // but with the current code it's hard to get the right information in the right place. const mobileTopbar = document.querySelector(".mobile-topbar"); const locationTitle = document.querySelector(".sidebar h2.location"); - if (mobileTopbar && locationTitle) { + if (mobileLocationTitle) { const mobileTitle = document.createElement("h2"); - mobileTitle.innerHTML = locationTitle.innerHTML; + if (hasClass(document.body, "crate")) { + mobileLocationTitle.innerText = `Crate ${window.currentCrate}`; + } else if (locationTitle) { + mobileLocationTitle.innerHTML = locationTitle.innerHTML; + } mobileTopbar.appendChild(mobileTitle); } } diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index 579c782be09..0987010b940 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -88,13 +88,21 @@ {% endif %} {# #} diff --git a/src/librustdoc/html/templates/sidebar.html b/src/librustdoc/html/templates/sidebar.html index 01d476ad29f..14a61f3643e 100644 --- a/src/librustdoc/html/templates/sidebar.html +++ b/src/librustdoc/html/templates/sidebar.html @@ -6,9 +6,6 @@ + {# #} + {# #} + {% if !layout.krate_version_extra.is_empty() %} +
{{+ layout.krate_version_extra}}
{# #} + {% endif %} {% endif %} {{ sidebar|safe }} {# #} diff --git a/tests/rustdoc/crate-version-extra.rs b/tests/rustdoc/crate-version-extra.rs new file mode 100644 index 00000000000..72a2c4ba5f7 --- /dev/null +++ b/tests/rustdoc/crate-version-extra.rs @@ -0,0 +1,7 @@ +// compile-flags: '--crate-version=1.3.37-nightly (203c57dbe 2023-09-17)' + +#![crate_name="foo"] + +// main version next to logo, extra version data below it +// @has 'foo/index.html' '//h2/span[@class="version"]' '1.3.37-nightly' +// @has 'foo/index.html' '//nav[@class="sidebar"]/div[@class="version"]' '(203c57dbe 2023-09-17)' From c6e6ecb1afea9695a42d0f148ce153536b279eb5 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 19 Sep 2023 16:28:18 -0700 Subject: [PATCH 4/9] rustdoc: remove rust logo from non-Rust crates --- compiler/rustc_arena/src/lib.rs | 2 + compiler/rustc_ast/src/lib.rs | 3 ++ compiler/rustc_codegen_ssa/src/lib.rs | 3 ++ compiler/rustc_driver_impl/src/lib.rs | 3 ++ compiler/rustc_errors/src/lib.rs | 2 + compiler/rustc_fluent_macro/src/lib.rs | 3 ++ compiler/rustc_graphviz/src/lib.rs | 3 ++ compiler/rustc_hir_analysis/src/lib.rs | 3 ++ compiler/rustc_incremental/src/lib.rs | 3 ++ compiler/rustc_infer/src/lib.rs | 3 ++ compiler/rustc_lint/src/lib.rs | 2 + compiler/rustc_llvm/src/lib.rs | 3 ++ compiler/rustc_metadata/src/lib.rs | 3 ++ compiler/rustc_middle/src/lib.rs | 2 + compiler/rustc_parse_format/src/lib.rs | 3 ++ compiler/rustc_passes/src/check_attr.rs | 13 ++++++ compiler/rustc_passes/src/lib.rs | 3 ++ compiler/rustc_plugin_impl/src/lib.rs | 3 ++ compiler/rustc_privacy/src/lib.rs | 3 ++ compiler/rustc_query_impl/src/lib.rs | 2 + compiler/rustc_resolve/src/lib.rs | 2 + compiler/rustc_serialize/src/lib.rs | 3 ++ compiler/rustc_smir/src/lib.rs | 3 ++ compiler/rustc_span/src/lib.rs | 2 + compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_symbol_mangling/src/lib.rs | 3 ++ compiler/rustc_target/src/lib.rs | 2 + compiler/rustc_trait_selection/src/lib.rs | 3 ++ compiler/rustc_ty_utils/src/lib.rs | 3 ++ library/alloc/src/lib.rs | 2 + library/core/src/lib.rs | 1 + library/proc_macro/src/lib.rs | 2 + library/std/src/lib.rs | 1 + library/test/src/lib.rs | 2 + src/doc/rustdoc/src/unstable-features.md | 15 +++++++ src/librustdoc/html/layout.rs | 37 ++++++++++++++--- src/librustdoc/html/render/context.rs | 12 +++--- src/librustdoc/html/render/write_shared.rs | 1 + src/librustdoc/html/sources.rs | 3 ++ src/librustdoc/html/static/css/rustdoc.css | 5 ++- src/librustdoc/html/templates/page.html | 44 +++++++++++---------- tests/rustdoc/logo-class-default.rs | 6 +-- tests/rustdoc/logo-class-rust.rs | 7 ++++ tests/rustdoc/logo-class.rs | 2 +- tests/ui/feature-gates/doc-rust-logo.rs | 5 +++ tests/ui/feature-gates/doc-rust-logo.stderr | 12 ++++++ 46 files changed, 208 insertions(+), 36 deletions(-) create mode 100644 tests/rustdoc/logo-class-rust.rs create mode 100644 tests/ui/feature-gates/doc-rust-logo.rs create mode 100644 tests/ui/feature-gates/doc-rust-logo.stderr diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index bf8a7eb293e..54274f15356 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -11,6 +11,8 @@ html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", test(no_crate_inject, attr(deny(warnings))) )] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] #![feature(new_uninit)] diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index b07ed1d1c74..ddc7c8ee825 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -8,6 +8,9 @@ html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", test(attr(deny(warnings))) )] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), allow(internal_features))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(const_trait_impl)] diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index f6186a290f8..b4728ac2aa6 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -1,4 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), allow(internal_features))] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(if_let_guard)] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 1b3f39e69e1..17556c45296 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -5,6 +5,9 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), allow(internal_features))] #![feature(lazy_cell)] #![feature(decl_macro)] #![feature(panic_update_hook)] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 665b5d6adec..63226504d37 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -3,6 +3,8 @@ //! This module contains the code for creating and emitting diagnostics. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![feature(array_windows)] #![feature(extract_if)] #![feature(if_let_guard)] diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs index a01643cd67d..191fb787f70 100644 --- a/compiler/rustc_fluent_macro/src/lib.rs +++ b/compiler/rustc_fluent_macro/src/lib.rs @@ -1,4 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), allow(internal_features))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_span)] #![deny(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index 5d86d895817..9cb279e3efd 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -273,6 +273,9 @@ html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", test(attr(allow(unused_variables), deny(warnings))) )] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), allow(internal_features))] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 03963925d3d..c7b3648099c 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -57,6 +57,9 @@ This API is completely unstable and subject to change. #![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), allow(internal_features))] #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(if_let_guard)] diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index 220ea194a6d..472dfe3dc4a 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -2,6 +2,9 @@ #![deny(missing_docs)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), allow(internal_features))] #![feature(never_type)] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index e92ba05aa67..4a6d1bc682b 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -13,6 +13,9 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), allow(internal_features))] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(control_flow_enum)] diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index af2132fb899..d7a666aa72b 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -27,6 +27,8 @@ #![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![feature(array_windows)] #![feature(box_patterns)] #![feature(control_flow_enum)] diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index eb70961503d..518c20c9fa8 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -1,6 +1,9 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), allow(internal_features))] // NOTE: This crate only exists to allow linking on mingw targets. diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index fa77b36c4c5..ddeb39669dc 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -1,4 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), allow(internal_features))] #![feature(decl_macro)] #![feature(extract_if)] #![feature(generators)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index fe4fc3761b3..dee18dc1162 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -23,6 +23,8 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![feature(allocator_api)] #![feature(array_windows)] #![feature(assert_matches)] diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 90ac436a91f..7b6153eea09 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -9,6 +9,9 @@ html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))) )] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), allow(internal_features))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] // We want to be able to build this crate with a stable compiler, so no diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 52fb193f3da..fbf3dff7560 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1108,6 +1108,7 @@ impl CheckAttrVisitor<'_> { | sym::html_root_url | sym::html_no_source | sym::test + | sym::rust_logo if !self.check_attr_crate_level(attr, meta, hir_id) => { is_valid = false; @@ -1166,6 +1167,18 @@ impl CheckAttrVisitor<'_> { | sym::plugins | sym::fake_variadic => {} + sym::rust_logo => { + if !self.tcx.features().rustdoc_internals { + feature_err( + &self.tcx.sess.parse_sess, + sym::rustdoc_internals, + meta.span(), + "the `#[doc(rust_logo)]` attribute is used for Rust branding", + ) + .emit(); + } + } + sym::test => { if !self.check_test_attr(meta, hir_id) { is_valid = false; diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 51f3c9ad76f..946a9e68da6 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -6,6 +6,9 @@ #![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), allow(internal_features))] #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(map_try_insert)] diff --git a/compiler/rustc_plugin_impl/src/lib.rs b/compiler/rustc_plugin_impl/src/lib.rs index faa7495ef9f..0e1c80a1f64 100644 --- a/compiler/rustc_plugin_impl/src/lib.rs +++ b/compiler/rustc_plugin_impl/src/lib.rs @@ -7,6 +7,9 @@ //! of the Unstable Book for some examples. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), allow(internal_features))] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index ab85f680fcf..21d7bcbed5e 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1,4 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), allow(internal_features))] #![feature(associated_type_defaults)] #![feature(rustc_private)] #![feature(try_blocks)] diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 30621a135eb..a1465dabed6 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -1,6 +1,8 @@ //! Support for serializing the dep-graph and reloading it. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] // this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref #![feature(const_mut_refs)] #![feature(const_refs_to_cell)] diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 5f012ec29fe..0bc45967e3d 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -7,6 +7,8 @@ //! Type-relative name resolution (methods, fields, associated items) happens in `rustc_hir_analysis`. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(extract_if)] diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index 5360aa9ea6a..cfa54072eb9 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -5,6 +5,9 @@ html_playground_url = "https://play.rust-lang.org/", test(attr(allow(unused_variables), deny(warnings))) )] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), allow(internal_features))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![feature(allocator_api)] #![feature(associated_type_bounds)] #![feature(const_option)] diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index d10f46fad9e..c24b9efe865 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -10,6 +10,9 @@ html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", test(attr(allow(unused_variables), deny(warnings))) )] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), allow(internal_features))] pub mod rustc_internal; diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 6fd61e45fcc..e62efab5793 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -14,6 +14,8 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![feature(array_windows)] #![feature(if_let_guard)] #![feature(negative_impls)] diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a62fa246ac4..ea261923c65 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1327,6 +1327,7 @@ symbols! { rust_cold_cc, rust_eh_catch_typeinfo, rust_eh_personality, + rust_logo, rustc, rustc_abi, rustc_allocator, diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 535a3ea2d7e..6ade2d777c7 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -88,6 +88,9 @@ //! DefPaths which are much more robust in the face of changes to the code base. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), allow(internal_features))] #![feature(never_type)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index e838e11131f..9c5ce889418 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -8,6 +8,8 @@ //! LLVM. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![feature(assert_matches)] #![feature(associated_type_bounds)] #![feature(exhaustive_patterns)] diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 56d37d58de7..5ba29f87855 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -11,6 +11,9 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), allow(internal_features))] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(control_flow_enum)] diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 147b600f7ba..1a9de150041 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -5,6 +5,9 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![cfg_attr(not(bootstrap), allow(internal_features))] #![feature(assert_matches)] #![feature(iterator_try_collect)] #![feature(let_chains)] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index cd3648214a4..d47f9de941c 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -78,6 +78,8 @@ not(no_sync), target_has_atomic = "ptr" ))] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![no_std] #![needs_allocator] // Lints: diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 7fa7e83a744..906421327cb 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -68,6 +68,7 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] +#![cfg_attr(not(bootstrap), doc(rust_logo))] #![doc(cfg_hide( not(test), any(not(feature = "miri-test-libstd"), test, doctest), diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 0a70c488aec..991fdb1256d 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -17,6 +17,8 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] // This library is copied into rust-analyzer to allow loading rustc compiled proc macros. // Please avoid unstable features where possible to minimize the amount of changes necessary // to make it compile with rust-analyzer on stable. diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 02f4d5bc7ae..aaf20875129 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -227,6 +227,7 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] +#![cfg_attr(not(bootstrap), doc(rust_logo))] #![doc(cfg_hide( not(test), not(any(test, bootstrap)), diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 413f0fba342..bddf75dffbb 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -16,6 +16,8 @@ #![unstable(feature = "test", issue = "50297")] #![doc(test(attr(deny(warnings))))] +#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] #![feature(internal_output_capture)] #![feature(staged_api)] #![feature(process_exitcode_internals)] diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 7473b09920f..199b5d69a1c 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -207,6 +207,21 @@ To do so, the `#[doc(keyword = "...")]` attribute is used. Example: mod empty_mod {} ``` +### Use the Rust logo as the crate logo + +This is for official Rust project use only. + +Internal Rustdoc pages like settings.html and scrape-examples-help.html show the Rust logo. +This logo is tracked as a static resource. The attribute `#![doc(rust_logo)]` makes this same +built-in resource act as the main logo. + +```rust +#![feature(rustdoc_internals)] +#![allow(internal_features)] +#![doc(rust_logo)] +//! This crate has the Rust(tm) branding on it. +``` + ## Effects of other nightly features These nightly-only features are not primarily related to Rustdoc, diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index d6e2330f91b..d4b4db0f3fd 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -18,7 +18,6 @@ pub(crate) struct Layout { pub(crate) default_settings: FxHashMap, pub(crate) krate: String, pub(crate) krate_version: String, - pub(crate) krate_version_extra: String, /// The given user css file which allow to customize the generated /// documentation theme. pub(crate) css_file_extension: Option, @@ -33,6 +32,7 @@ pub(crate) struct Page<'a> { pub(crate) static_root_path: Option<&'a str>, pub(crate) description: &'a str, pub(crate) resource_suffix: &'a str, + pub(crate) rust_logo: bool, } impl<'a> Page<'a> { @@ -56,9 +56,19 @@ struct PageLayout<'a> { themes: Vec, sidebar: String, content: String, - krate_with_trailing_slash: String, rust_channel: &'static str, pub(crate) rustdoc_version: &'a str, + // same as layout.krate, except on top-level pages like + // Settings, Help, All Crates, and About Scraped Examples, + // where these things instead give Rustdoc name and version. + // + // These are separate from the variables used for the search + // engine, because "Rustdoc" isn't necessarily a crate in + // the current workspace. + display_krate: &'a str, + display_krate_with_trailing_slash: String, + display_krate_version_number: &'a str, + display_krate_version_extra: &'a str, } pub(crate) fn render( @@ -68,12 +78,26 @@ pub(crate) fn render( t: T, style_files: &[StylePath], ) -> String { + let rustdoc_version = rustc_interface::util::version_str!().unwrap_or("unknown version"); + + let (display_krate, display_krate_version, display_krate_with_trailing_slash) = + if page.root_path == "./" { + // top level pages use Rust branding + ("Rustdoc", rustdoc_version, String::new()) + } else { + let display_krate_with_trailing_slash = + ensure_trailing_slash(&layout.krate).to_string(); + (&layout.krate[..], &layout.krate_version[..], display_krate_with_trailing_slash) + }; let static_root_path = page.get_static_root_path(); - let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string(); + + // bootstrap passes in parts of the version separated by tabs, but other stuff might use spaces + let (display_krate_version_number, display_krate_version_extra) = + display_krate_version.split_once([' ', '\t']).unwrap_or((display_krate_version, "")); + let mut themes: Vec = style_files.iter().map(|s| s.basename().unwrap()).collect(); themes.sort(); - let rustdoc_version = rustc_interface::util::version_str!().unwrap_or("unknown version"); let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar. let sidebar = Buffer::html().to_display(sidebar); PageLayout { @@ -84,7 +108,10 @@ pub(crate) fn render( themes, sidebar, content, - krate_with_trailing_slash, + display_krate, + display_krate_with_trailing_slash, + display_krate_version_number, + display_krate_version_extra, rust_channel: *crate::clean::utils::DOC_CHANNEL, rustdoc_version, } diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 160233d99ac..da826054e66 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -24,6 +24,7 @@ use super::{ sidebar::{sidebar_module_like, Sidebar}, AllTypes, LinkFromSrc, StylePath, }; +use crate::clean::utils::has_doc_flag; use crate::clean::{self, types::ExternalLocation, ExternalCrate, TypeAliasItem}; use crate::config::{ModuleSorting, RenderOptions}; use crate::docfs::{DocFS, PathError}; @@ -277,6 +278,7 @@ impl<'tcx> Context<'tcx> { title: &title, description: &desc, resource_suffix: &clone_shared.resource_suffix, + rust_logo: has_doc_flag(self.tcx(), LOCAL_CRATE.as_def_id(), sym::rust_logo), }; let mut page_buffer = Buffer::html(); print_item(self, it, &mut page_buffer, &page); @@ -529,8 +531,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { playground = Some(markdown::Playground { crate_name: Some(krate.name(tcx)), url }); } let krate_version = cache.crate_version.as_deref().unwrap_or_default(); - let (krate_version, krate_version_extra) = - krate_version.split_once(" ").unwrap_or((krate_version, "")); let mut layout = layout::Layout { logo: String::new(), favicon: String::new(), @@ -538,7 +538,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { default_settings, krate: krate.name(tcx).to_string(), krate_version: krate_version.to_string(), - krate_version_extra: krate_version_extra.to_string(), css_file_extension: extension_css, scrape_examples_extension: !call_locations.is_empty(), }; @@ -668,6 +667,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { static_root_path: shared.static_root_path.as_deref(), description: "List of all items in this crate", resource_suffix: &shared.resource_suffix, + rust_logo: has_doc_flag(self.tcx(), LOCAL_CRATE.as_def_id(), sym::rust_logo), }; let all = shared.all.replace(AllTypes::new()); let mut sidebar = Buffer::html(); @@ -693,9 +693,10 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { shared.fs.write(final_file, v)?; // Generating settings page. - page.title = "Rustdoc settings"; + page.title = "Settings"; page.description = "Settings of Rustdoc"; page.root_path = "./"; + page.rust_logo = true; let sidebar = "

Settings

"; let v = layout::render( @@ -743,9 +744,10 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { shared.fs.write(settings_file, v)?; // Generating help page. - page.title = "Rustdoc help"; + page.title = "Help"; page.description = "Documentation for Rustdoc"; page.root_path = "./"; + page.rust_logo = true; let sidebar = "

Help

"; let v = layout::render( diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index e824651e727..eea7193ccbe 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -341,6 +341,7 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; static_root_path: shared.static_root_path.as_deref(), description: "List of crates", resource_suffix: &shared.resource_suffix, + rust_logo: true, }; let content = format!( diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 1d6eafe51b9..4a218b9b37c 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -1,4 +1,5 @@ use crate::clean; +use crate::clean::utils::has_doc_flag; use crate::docfs::PathError; use crate::error::Error; use crate::html::format; @@ -13,6 +14,7 @@ use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::source_map::FileName; +use rustc_span::sym; use std::cell::RefCell; use std::ffi::OsStr; @@ -231,6 +233,7 @@ impl SourceCollector<'_, '_> { static_root_path: shared.static_root_path.as_deref(), description: &desc, resource_suffix: &shared.resource_suffix, + rust_logo: has_doc_flag(self.cx.tcx(), LOCAL_CRATE.as_def_id(), sym::rust_logo), }; let v = layout::render( &shared.layout, diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 5e1bccb9b5b..f5bbda938e4 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -521,7 +521,8 @@ ul.block, .block li { display: flex; align-items: center; justify-content: center; - margin: 0 32px; + margin: 10px 32px 0; + row-gap: 10px; column-gap: 32px; flex-wrap: wrap; } @@ -540,7 +541,7 @@ ul.block, .block li { } .sidebar-crate .logo-container { - margin: 10px -16px; + margin: 0 -16px; text-align: center; } diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index 4a7c06e63c9..612f8613482 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -77,34 +77,38 @@ {% if page.css_class != "src" %} {% endif %}