mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-13 20:46:48 +00:00
Auto merge of #115948 - notriddle:notriddle/logo-lockup, r=fmease
rustdoc: show crate name beside smaller logo *Blocked on https://github.com/rust-lang/cargo/pull/12800* ## Summary In this PR, the crate name and version are always shown in the sidebar, even in subpages, and the lateral navigation is always shown in the sidebar, even in modules. Clicking the crate name does the same thing clicking the logo always did: take you to the crate root (the crate's home page, at least within Rustdoc). The Rust logo is also no longer shown by default for non-Rust docs. ### Screenshots <details><summary>Before</summary> | | Macro | Module | |--|-------|--------| | In crate |  | | In module[^1] |  |  [^1]: This PR also includes a bug fix for derive macros not showing up in the lateral navigation part of the sidebar </details> #### Whole sidebar screenshots | | Macro | Module | |--|-------|--------| | In crate |  |  | In module |  |  #### Different logo configurations | | 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/9e2b4fa8-f581-4106-b562-1e0372c13f79 [short-subpage]: https://github.com/rust-lang/rust/assets/1593513/8331cdb8-fa13-4671-a1e2-dcc1cdca7451 [long-root]: https://github.com/rust-lang/rust/assets/1593513/7d377fec-0f1d-4343-9f82-0e35a8f58056 [long-subpage]: https://github.com/rust-lang/rust/assets/1593513/3b3094a4-63c9-477c-8c15-b6075837df30 ##### Without a logo  ### Preview pages https://notriddle.com/rustdoc-html-demo-5/sidebar-layout-rocket/rocket/index.html https://notriddle.com/rustdoc-html-demo-5/sidebar-layout-rocket/rocket_sync_db_pools/index.html https://notriddle.com/rustdoc-html-demo-5/sidebar-layout-rust-compiler/index.html https://notriddle.com/rustdoc-html-demo-5/sidebar-layout-rust/std/index.html https://notriddle.com/rustdoc-html-demo-5/sidebar-layout-rocket/tokio/index.html ## Motivation 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 ## Guide-level explanation This PR cleans up some of the sidebar navigation. It makes the logo in the desktop sidebar a bit smaller, and puts the crate name and version next to it (either beside it, or below it, depending on if there's space), making it clearer what clicking on it does: click the crate name to open the crate's home page. It also removes the Rust logo from non-official-Rust crates, again to make the navigation and supply chain clearer (since the crate name has been added, the logo is no longer necessary for navigation). It adds a bit more clarifying information for lateral navigation. On items that don't add their own sidebar items, it just shows its siblings directly below the crate name and logo, but for other items, it shows "In crate alloc" instead of just "In alloc". It also shows the lateral navigation tools on module pages, making modules consistent with every other item. ## Drawbacks 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. ## Rationale and alternatives 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. ## Prior art 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 ## Unresolved questions Maybe we should encourage crate authors to include their own logo more often? It certainly helps give people a better sense of "place." This seems to be blocked on coming up with an API to do it without requiring them to host the file somewhere. ## Future possibilities Beyond this, plenty of other changes could be made to improve the layout, like * Fix things so that clicking an item in the sidebar doesn't cause it to scroll back to the top. * The [Internals demo](https://utherii.github.io/new.html) does this right: clicking an item in the sidebar changes the content area, but the sidebar itself does not change. This is nice, because clicking is cheap and I can skim the opening few paragraphs while browsing. * The layout of the docs sidebar causes trouble to implement this, because it's different on different pages, but at least fix this on the file browser. * Come up with a less cluttered way to do disclosure. There's a lot of `[-]` on the page. * We don't lack ideas to fix this one. We have *too many*. * Do a better job of separating local navigation (vec::Vec links to vec::IntoIter) and the table of contents (vec::Vec links to vec::Vec::new). * A possibility: add a Back arrow next to the "In [module]" header?  * Give readers more control of how much rustdoc shows them, and giving doc authors more control of how much it generates. Basically, https://github.com/rust-lang/rust/pull/115660 is great, let's do it too. But those are mostly orthogonal, not future possibilities unlocked by this change.
This commit is contained in:
commit
6d05c430d2
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -1327,6 +1327,7 @@ symbols! {
|
||||
rust_cold_cc,
|
||||
rust_eh_catch_typeinfo,
|
||||
rust_eh_personality,
|
||||
rust_logo,
|
||||
rustc,
|
||||
rustc_abi,
|
||||
rustc_allocator,
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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)]
|
||||
|
@ -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:
|
||||
|
@ -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),
|
||||
|
@ -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.
|
||||
|
@ -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)),
|
||||
|
@ -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)]
|
||||
|
@ -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,
|
||||
|
@ -17,6 +17,7 @@ pub(crate) struct Layout {
|
||||
pub(crate) external_html: ExternalHtml,
|
||||
pub(crate) default_settings: FxHashMap<String, String>,
|
||||
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<PathBuf>,
|
||||
@ -31,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> {
|
||||
@ -54,9 +56,19 @@ struct PageLayout<'a> {
|
||||
themes: Vec<String>,
|
||||
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<T: Print, S: Print>(
|
||||
@ -66,12 +78,26 @@ pub(crate) fn render<T: Print, S: Print>(
|
||||
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<String> = 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 {
|
||||
@ -82,7 +108,10 @@ pub(crate) fn render<T: Print, S: Print>(
|
||||
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,
|
||||
}
|
||||
|
@ -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);
|
||||
@ -528,12 +530,14 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||
if let Some(url) = playground_url {
|
||||
playground = Some(markdown::Playground { crate_name: Some(krate.name(tcx)), url });
|
||||
}
|
||||
let krate_version = cache.crate_version.as_deref().unwrap_or_default();
|
||||
let mut layout = layout::Layout {
|
||||
logo: String::new(),
|
||||
favicon: String::new(),
|
||||
external_html,
|
||||
default_settings,
|
||||
krate: krate.name(tcx).to_string(),
|
||||
krate_version: krate_version.to_string(),
|
||||
css_file_extension: extension_css,
|
||||
scrape_examples_extension: !call_locations.is_empty(),
|
||||
};
|
||||
@ -658,21 +662,22 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||
let shared = Rc::clone(&self.shared);
|
||||
let mut page = layout::Page {
|
||||
title: "List of all items in this crate",
|
||||
css_class: "mod",
|
||||
css_class: "mod sys",
|
||||
root_path: "../",
|
||||
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();
|
||||
|
||||
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: "",
|
||||
is_mod: false,
|
||||
blocks: vec![blocks],
|
||||
path: String::new(),
|
||||
};
|
||||
@ -689,9 +694,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 = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
|
||||
let v = layout::render(
|
||||
@ -739,9 +745,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 = "<h2 class=\"location\">Help</h2><div class=\"sidebar-elems\"></div>";
|
||||
let v = layout::render(
|
||||
|
@ -2094,6 +2094,7 @@ impl ItemSection {
|
||||
const ALL: &'static [Self] = {
|
||||
use ItemSection::*;
|
||||
// NOTE: The order here affects the order in the UI.
|
||||
// Keep this synchronized with addSidebarItems in main.js
|
||||
&[
|
||||
Reexports,
|
||||
PrimitiveTypes,
|
||||
|
@ -19,7 +19,7 @@ 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) is_mod: bool,
|
||||
pub(super) blocks: Vec<LinkBlock<'a>>,
|
||||
pub(super) path: String,
|
||||
}
|
||||
@ -99,12 +99,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 +113,22 @@ 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()
|
||||
// need to show parent path header if:
|
||||
// - it's a child module, instead of the crate root
|
||||
// - there's a sidebar section for the item itself
|
||||
//
|
||||
// otherwise, the parent path header is redundant with the big crate
|
||||
// branding area at the top of the sidebar
|
||||
let sidebar_path =
|
||||
if it.is_mod() { &cx.current[..cx.current.len() - 1] } else { &cx.current[..] };
|
||||
let path: String = if sidebar_path.len() > 1 || !title.is_empty() {
|
||||
let path = sidebar_path.iter().map(|s| s.as_str()).intersperse("::").collect();
|
||||
if sidebar_path.len() == 1 { format!("crate {path}") } else { path }
|
||||
} else {
|
||||
"".into()
|
||||
};
|
||||
let sidebar = Sidebar { title_prefix, title, is_crate: it.is_crate(), version, blocks, path };
|
||||
let sidebar =
|
||||
Sidebar { title_prefix, title, is_mod: it.is_mod(), is_crate: it.is_crate(), blocks, path };
|
||||
sidebar.render_into(buffer).unwrap();
|
||||
}
|
||||
|
||||
|
@ -336,11 +336,12 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
|
||||
let dst = cx.dst.join("index.html");
|
||||
let page = layout::Page {
|
||||
title: "Index of crates",
|
||||
css_class: "mod",
|
||||
css_class: "mod sys",
|
||||
root_path: "./",
|
||||
static_root_path: shared.static_root_path.as_deref(),
|
||||
description: "List of crates",
|
||||
resource_suffix: &shared.resource_suffix,
|
||||
rust_logo: true,
|
||||
};
|
||||
|
||||
let content = format!(
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
@ -502,6 +492,7 @@ ul.block, .block li {
|
||||
}
|
||||
|
||||
.sidebar-elems,
|
||||
.sidebar > .version,
|
||||
.sidebar > h2 {
|
||||
padding-left: 24px;
|
||||
}
|
||||
@ -510,6 +501,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 +517,75 @@ ul.block, .block li {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sidebar-crate {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/* there's a 10px padding at the top of <main>, and a 4px margin at the
|
||||
top of the search form. To line them up, add them. */
|
||||
margin: 14px 32px 1rem;
|
||||
row-gap: 10px;
|
||||
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;
|
||||
/* To align this with the search bar, it should not be centered, even when
|
||||
the logo is. */
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
.sidebar-crate .logo-container {
|
||||
/* The logo is expected to have 8px "slop" along its edges, so we can optically
|
||||
center it. */
|
||||
margin: 0 -16px 0 -16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sidebar-crate h2 a {
|
||||
display: block;
|
||||
margin: 0 calc(-24px + 0.25rem) 0 -0.5rem;
|
||||
/* Align the sidebar crate link with the search bar, which have different
|
||||
font sizes.
|
||||
|
||||
| | font-size | line-height | total line-height | padding-y | total |
|
||||
|:-------|----------:|------------:|------------------:|----------:|-------------:|
|
||||
| crate | 1.375rem | 1.25 | 1.72rem | x | 2x+1.72rem |
|
||||
| search | 1rem | 1.15 | 1.15rem | 8px | 1.15rem+16px |
|
||||
|
||||
2x + 1.72rem = 1.15rem + 16px
|
||||
2x = 1.15rem + 16px - 1.72rem
|
||||
2x = 16px - 0.57rem
|
||||
x = ( 16px - 0.57rem ) / 2
|
||||
*/
|
||||
padding: calc( ( 16px - 0.57rem ) / 2 ) 0.25rem;
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
|
||||
.sidebar-crate h2 .version {
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
font-size: 1rem;
|
||||
overflow-wrap: break-word;
|
||||
/* opposite of the link padding, cut in half again */
|
||||
margin-top: calc( ( -16px + 0.57rem ) / 2 );
|
||||
}
|
||||
|
||||
.sidebar-crate + .version {
|
||||
margin-top: -1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.mobile-topbar {
|
||||
display: none;
|
||||
}
|
||||
|
@ -51,9 +51,14 @@ 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 (mobileTopbar) {
|
||||
const mobileTitle = document.createElement("h2");
|
||||
mobileTitle.innerHTML = locationTitle.innerHTML;
|
||||
mobileTitle.className = "location";
|
||||
if (hasClass(document.body, "crate")) {
|
||||
mobileTitle.innerText = `Crate ${window.currentCrate}`;
|
||||
} else if (locationTitle) {
|
||||
mobileTitle.innerHTML = locationTitle.innerHTML;
|
||||
}
|
||||
mobileTopbar.appendChild(mobileTitle);
|
||||
}
|
||||
}
|
||||
@ -480,22 +485,27 @@ function preLoadCss(cssUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
const modpath = hasClass(document.body, "mod") ? "../" : "";
|
||||
|
||||
const h3 = document.createElement("h3");
|
||||
h3.innerHTML = `<a href="index.html#${id}">${longty}</a>`;
|
||||
h3.innerHTML = `<a href="${modpath}index.html#${id}">${longty}</a>`;
|
||||
const ul = document.createElement("ul");
|
||||
ul.className = "block " + shortty;
|
||||
|
||||
for (const name of filtered) {
|
||||
let path;
|
||||
if (shortty === "mod") {
|
||||
path = name + "/index.html";
|
||||
path = `${modpath}${name}/index.html`;
|
||||
} else {
|
||||
path = shortty + "." + name + ".html";
|
||||
path = `${modpath}${shortty}.${name}.html`;
|
||||
}
|
||||
let current_page = document.location.href.toString();
|
||||
if (current_page.endsWith("/")) {
|
||||
current_page += "index.html";
|
||||
}
|
||||
const current_page = document.location.href.split("/").pop();
|
||||
const link = document.createElement("a");
|
||||
link.href = path;
|
||||
if (path === current_page) {
|
||||
if (link.href === current_page) {
|
||||
link.className = "current";
|
||||
}
|
||||
link.textContent = name;
|
||||
@ -508,19 +518,33 @@ function preLoadCss(cssUrl) {
|
||||
}
|
||||
|
||||
if (sidebar) {
|
||||
// keep this synchronized with ItemSection::ALL in html/render/mod.rs
|
||||
// Re-exports aren't shown here, because they don't have child pages
|
||||
//block("reexport", "reexports", "Re-exports");
|
||||
block("primitive", "primitives", "Primitive Types");
|
||||
block("mod", "modules", "Modules");
|
||||
block("macro", "macros", "Macros");
|
||||
block("struct", "structs", "Structs");
|
||||
block("enum", "enums", "Enums");
|
||||
block("union", "unions", "Unions");
|
||||
block("constant", "constants", "Constants");
|
||||
block("static", "static", "Statics");
|
||||
block("trait", "traits", "Traits");
|
||||
block("fn", "functions", "Functions");
|
||||
block("type", "types", "Type Aliases");
|
||||
block("union", "unions", "Unions");
|
||||
// No point, because these items don't appear in modules
|
||||
//block("impl", "impls", "Implementations");
|
||||
//block("tymethod", "tymethods", "Type Methods");
|
||||
//block("method", "methods", "Methods");
|
||||
//block("structfield", "fields", "Fields");
|
||||
//block("variant", "variants", "Variants");
|
||||
//block("associatedtype", "associated-types", "Associated Types");
|
||||
//block("associatedconstant", "associated-consts", "Associated Constants");
|
||||
block("foreigntype", "foreign-types", "Foreign Types");
|
||||
block("keyword", "keywords", "Keywords");
|
||||
block("opaque", "opaque-types", "Opaque Types");
|
||||
block("attr", "attributes", "Attribute Macros");
|
||||
block("derive", "derives", "Derive Macros");
|
||||
block("traitalias", "trait-aliases", "Trait Aliases");
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,8 @@
|
||||
<script defer src="{{page.root_path|safe}}src-files{{page.resource_suffix}}.js"></script> {# #}
|
||||
{% else if !page.css_class.contains("mod") %}
|
||||
<script defer src="sidebar-items{{page.resource_suffix}}.js"></script> {# #}
|
||||
{% else if !page.css_class.contains("sys") %}
|
||||
<script defer src="../sidebar-items{{page.resource_suffix}}.js"></script> {# #}
|
||||
{% endif %}
|
||||
<script defer src="{{static_root_path|safe}}{{files.main_js}}"></script> {# #}
|
||||
{% if layout.scrape_examples_extension %}
|
||||
@ -77,36 +79,51 @@
|
||||
{% if page.css_class != "src" %}
|
||||
<nav class="mobile-topbar"> {# #}
|
||||
<button class="sidebar-menu-toggle">☰</button> {# #}
|
||||
<a class="logo-container" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {# #}
|
||||
{% if !layout.logo.is_empty() %}
|
||||
<img src="{{layout.logo}}" alt="logo"> {# #}
|
||||
{% else %}
|
||||
<img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {# #}
|
||||
{% if !layout.logo.is_empty() || page.rust_logo %}
|
||||
<a class="logo-container" href="{{page.root_path|safe}}{{display_krate_with_trailing_slash|safe}}index.html"> {# #}
|
||||
{% if page.rust_logo %}
|
||||
<img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt=""> {# #}
|
||||
{% else if !layout.logo.is_empty() %}
|
||||
<img src="{{layout.logo}}" alt=""> {# #}
|
||||
{% endif %}
|
||||
</a> {# #}
|
||||
{% endif %}
|
||||
</nav>
|
||||
{% endif %}
|
||||
<nav class="sidebar"> {# #}
|
||||
{% if page.css_class != "src" %}
|
||||
<a class="logo-container" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {# #}
|
||||
{% if !layout.logo.is_empty() %}
|
||||
<img src="{{layout.logo}}" alt="logo"> {# #}
|
||||
{% else %}
|
||||
<img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {# #}
|
||||
<div class="sidebar-crate">
|
||||
{% if !layout.logo.is_empty() || page.rust_logo %}
|
||||
<a class="logo-container" href="{{page.root_path|safe}}{{display_krate_with_trailing_slash|safe}}index.html"> {# #}
|
||||
{% if page.rust_logo %}
|
||||
<img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {# #}
|
||||
{% else if !layout.logo.is_empty() %}
|
||||
<img src="{{layout.logo}}" alt="logo"> {# #}
|
||||
{% endif %}
|
||||
</a> {# #}
|
||||
{% endif %}
|
||||
</a> {# #}
|
||||
<h2> {# #}
|
||||
<a href="{{page.root_path|safe}}{{display_krate_with_trailing_slash|safe}}index.html">{{display_krate}}</a> {# #}
|
||||
{% if !display_krate_version_number.is_empty() %}
|
||||
<span class="version">{{+ display_krate_version_number}}</span>
|
||||
{% endif %}
|
||||
</h2> {# #}
|
||||
</div> {# #}
|
||||
{% if !display_krate_version_extra.is_empty() %}
|
||||
<div class="version">{{+ display_krate_version_extra}}</div> {# #}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{{ sidebar|safe }}
|
||||
</nav> {# #}
|
||||
<main> {# #}
|
||||
{% if page.css_class != "src" %}<div class="width-limiter">{% endif %}
|
||||
<nav class="sub"> {# #}
|
||||
{% if page.css_class == "src" %}
|
||||
<a class="sub-logo-container" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {# #}
|
||||
{% if !layout.logo.is_empty() %}
|
||||
<img src="{{layout.logo}}" alt="logo"> {# #}
|
||||
{% else %}
|
||||
<img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {# #}
|
||||
{% if page.css_class == "src" && (!layout.logo.is_empty() || page.rust_logo) %}
|
||||
<a class="sub-logo-container" href="{{page.root_path|safe}}{{display_krate_with_trailing_slash|safe}}index.html"> {# #}
|
||||
{% if page.rust_logo %}
|
||||
<img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="{{display_krate}}"> {# #}
|
||||
{% else if !layout.logo.is_empty() %}
|
||||
<img src="{{layout.logo}}" alt="{{display_krate}}"> {# #}
|
||||
{% endif %}
|
||||
</a> {# #}
|
||||
{% endif %}
|
||||
|
@ -6,9 +6,6 @@
|
||||
<div class="sidebar-elems">
|
||||
{% if is_crate %}
|
||||
<ul class="block">
|
||||
{% if !version.is_empty() %}
|
||||
<li class="version">Version {{+ version}}</li>
|
||||
{% endif %}
|
||||
<li><a id="all-types" href="all.html">All Items</a></li> {# #}
|
||||
</ul>
|
||||
{% endif %}
|
||||
@ -32,6 +29,6 @@
|
||||
</section>
|
||||
{% endif %}
|
||||
{% if !path.is_empty() %}
|
||||
<h2><a href="index.html">In {{+ path}}</a></h2>
|
||||
<h2><a href="{% if is_mod %}../{% endif %}index.html">In {{+ path}}</a></h2>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
@ -322,7 +322,15 @@ impl TestProps {
|
||||
);
|
||||
|
||||
if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
|
||||
self.compile_flags.extend(flags.split_whitespace().map(|s| s.to_owned()));
|
||||
self.compile_flags.extend(
|
||||
flags
|
||||
.split("'")
|
||||
.enumerate()
|
||||
.flat_map(|(i, f)| {
|
||||
if i % 2 == 1 { vec![f] } else { f.split_whitespace().collect() }
|
||||
})
|
||||
.map(|s| s.to_owned()),
|
||||
);
|
||||
}
|
||||
if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() {
|
||||
panic!("`compiler-flags` directive should be spelled `compile-flags`");
|
||||
|
@ -56,7 +56,7 @@ define-function: (
|
||||
|
||||
assert-css: ("#top-doc-prose-title", {"color": |title_color|})
|
||||
|
||||
assert-css: (".sidebar a", {"color": |sidebar_link_color|})
|
||||
assert-css: (".sidebar .block a", {"color": |sidebar_link_color|})
|
||||
assert-css: (".main-heading h1 a", {"color": |title_color|})
|
||||
|
||||
// We move the cursor over the "Implementations" title so the anchor is displayed.
|
||||
|
@ -4,8 +4,8 @@ go-to: "file://" + |DOC_PATH| + "/huge_logo/index.html"
|
||||
|
||||
set-window-size: (1280, 1024)
|
||||
// offsetWidth = width of sidebar
|
||||
assert-property: (".sidebar .logo-container", {"offsetWidth": "200", "offsetHeight": 100})
|
||||
assert-property: (".sidebar .logo-container img", {"offsetWidth": "100", "offsetHeight": 100})
|
||||
assert-property: (".sidebar-crate .logo-container", {"offsetWidth": "48", "offsetHeight": 48})
|
||||
assert-property: (".sidebar-crate .logo-container img", {"offsetWidth": "48", "offsetHeight": 48})
|
||||
|
||||
set-window-size: (400, 600)
|
||||
// offset = size + margin
|
||||
|
@ -1,18 +1,18 @@
|
||||
// This test ensures that the correct style is applied to the rust logo in the sidebar.
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
go-to: "file://" + |DOC_PATH| + "/staged_api/index.html"
|
||||
|
||||
define-function: (
|
||||
"check-logo",
|
||||
(theme, filter),
|
||||
block {
|
||||
// Going to the doc page.
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
go-to: "file://" + |DOC_PATH| + "/staged_api/index.html"
|
||||
// Changing theme.
|
||||
set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
|
||||
reload:
|
||||
assert-css: (".rust-logo", {"filter": |filter|})
|
||||
// Going to the source code page.
|
||||
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
|
||||
go-to: "file://" + |DOC_PATH| + "/src/staged_api/lib.rs.html"
|
||||
// Changing theme (since it's local files, the local storage works by folder).
|
||||
set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
|
||||
reload:
|
||||
@ -26,6 +26,15 @@ define-function: (
|
||||
assert-false: ".rust-logo"
|
||||
// Check there is no filter.
|
||||
assert-css: (".sidebar .logo-container img", {"filter": "none"})
|
||||
// Now we check that this page has no logo at all
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
assert-false: ".rust-logo"
|
||||
assert-false: ".logo-container"
|
||||
assert-false: ".sub-logo-container"
|
||||
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
|
||||
assert-false: ".rust-logo"
|
||||
assert-false: ".logo-container"
|
||||
assert-false: ".sub-logo-container"
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -26,7 +26,7 @@ assert-css: (".sidebar", {"left": "0px"})
|
||||
// Make sure the "struct Foo" header is hidden, since the mobile topbar already does it.
|
||||
assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[text()='Foo']/parent::h2", {"display": "none"})
|
||||
// Make sure the global navigation is still here.
|
||||
assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[text()='In test_docs']/parent::h2", {"display": "block"})
|
||||
assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[text()='In crate test_docs']/parent::h2", {"display": "block"})
|
||||
|
||||
// Click elsewhere.
|
||||
click: "body"
|
||||
@ -50,7 +50,7 @@ assert-position: ("#method\.must_use", {"y": 46})
|
||||
// Check that the bottom-most item on the sidebar menu can be scrolled fully into view.
|
||||
click: ".sidebar-menu-toggle"
|
||||
scroll-to: ".block.keyword li:nth-child(1)"
|
||||
compare-elements-position-near: (".block.keyword li:nth-child(1)", ".mobile-topbar", {"y": 543.19})
|
||||
compare-elements-position-near: (".block.keyword li:nth-child(1)", ".mobile-topbar", {"y": 544})
|
||||
|
||||
// Now checking the background color of the sidebar.
|
||||
show-text: true
|
||||
|
@ -174,14 +174,14 @@ click: "#src-sidebar-toggle"
|
||||
wait-for-css: (".sidebar", {"left": "-1000px"})
|
||||
// We scroll to line 117 to change the scroll position.
|
||||
scroll-to: '//*[@id="117"]'
|
||||
assert-window-property: {"pageYOffset": "2542"}
|
||||
assert-window-property: {"pageYOffset": "2516"}
|
||||
// Expanding the sidebar...
|
||||
click: "#src-sidebar-toggle"
|
||||
wait-for-css: (".sidebar", {"left": "0px"})
|
||||
click: "#src-sidebar-toggle"
|
||||
wait-for-css: (".sidebar", {"left": "-1000px"})
|
||||
// The "scrollTop" property should be the same.
|
||||
assert-window-property: {"pageYOffset": "2542"}
|
||||
assert-window-property: {"pageYOffset": "2516"}
|
||||
|
||||
// We now check that opening the sidebar and clicking a link will close it.
|
||||
// The behavior here on mobile is different than the behavior on desktop,
|
||||
|
@ -50,9 +50,9 @@ set-local-storage: {"rustdoc-theme": "light"}
|
||||
// We reload the page so the local storage settings are being used.
|
||||
reload:
|
||||
|
||||
assert-text: (".sidebar > .location", "Crate test_docs")
|
||||
// In modules, we only have one "location" element.
|
||||
assert-count: (".sidebar .location", 1)
|
||||
assert-text: (".sidebar > .sidebar-crate > h2 > a", "test_docs")
|
||||
// Crate root has no "location" element
|
||||
assert-count: (".sidebar .location", 0)
|
||||
assert-count: (".sidebar h2", 1)
|
||||
assert-text: ("#all-types", "All Items")
|
||||
assert-css: ("#all-types", {"color": "#356da4"})
|
||||
@ -74,8 +74,9 @@ assert-text: ("#structs + .item-table .item-name > a", "Foo")
|
||||
click: "#structs + .item-table .item-name > a"
|
||||
|
||||
// PAGE: struct.Foo.html
|
||||
assert-count: (".sidebar .sidebar-crate", 1)
|
||||
assert-count: (".sidebar .location", 1)
|
||||
assert-count: (".sidebar h2", 2)
|
||||
assert-count: (".sidebar h2", 3)
|
||||
// We check that there is no crate listed outside of the top level.
|
||||
assert-false: ".sidebar-elems > .crate"
|
||||
|
||||
@ -94,7 +95,8 @@ click: ".sidebar-elems ul.crate > li:first-child > a"
|
||||
// PAGE: lib2/index.html
|
||||
go-to: "file://" + |DOC_PATH| + "/lib2/index.html"
|
||||
assert-property: (".sidebar", {"clientWidth": "200"})
|
||||
assert-text: (".sidebar > .location", "Crate lib2")
|
||||
assert-text: (".sidebar > .sidebar-crate > h2 > a", "lib2")
|
||||
assert-count: (".sidebar .location", 0)
|
||||
// We check that we have the crates list and that the "current" on is now "lib2".
|
||||
assert-text: (".sidebar-elems ul.crate > li > a.current", "lib2")
|
||||
// We now go to the "foobar" function page.
|
||||
@ -108,22 +110,39 @@ click: "#functions + .item-table .item-name > a"
|
||||
|
||||
// PAGE: fn.foobar.html
|
||||
// In items containing no items (like functions or constants) and in modules, we have no
|
||||
// "location" elements. Only the parent module h2.
|
||||
// "location" elements. Only the crate and optional parent module.
|
||||
// This page, being directly below the crate, only has its heading.
|
||||
assert-text: (".sidebar > .sidebar-crate > h2 > a", "lib2")
|
||||
assert-count: (".sidebar .location", 0)
|
||||
assert-count: (".sidebar h2", 1)
|
||||
assert-text: (".sidebar .sidebar-elems h2", "In lib2")
|
||||
// We check that we don't have the crate list.
|
||||
assert-false: ".sidebar-elems > .crate"
|
||||
|
||||
go-to: "./module/index.html"
|
||||
assert-property: (".sidebar", {"clientWidth": "200"})
|
||||
assert-text: (".sidebar > .sidebar-crate > h2 > a", "lib2")
|
||||
assert-text: (".sidebar > .location", "Module module")
|
||||
assert-count: (".sidebar .location", 1)
|
||||
// Module page requires three headings:
|
||||
// - Presistent crate branding (name and version)
|
||||
// - Module name, followed by TOC for module headings
|
||||
// - "In crate [name]" parent pointer, followed by sibling navigation
|
||||
assert-count: (".sidebar h2", 3)
|
||||
assert-text: (".sidebar > .sidebar-elems > h2", "In crate lib2")
|
||||
assert-property: (".sidebar > .sidebar-elems > h2 > a", {
|
||||
"href": "/lib2/index.html",
|
||||
}, ENDS_WITH)
|
||||
// We check that we don't have the crate list.
|
||||
assert-false: ".sidebar-elems > .crate"
|
||||
|
||||
go-to: "./sub_module/sub_sub_module/index.html"
|
||||
assert-property: (".sidebar", {"clientWidth": "200"})
|
||||
assert-text: (".sidebar > .sidebar-crate > h2 > a", "lib2")
|
||||
assert-text: (".sidebar > .location", "Module sub_sub_module")
|
||||
assert-text: (".sidebar > .sidebar-elems > h2", "In lib2::module::sub_module")
|
||||
assert-property: (".sidebar > .sidebar-elems > h2 > a", {
|
||||
"href": "/module/sub_module/index.html",
|
||||
}, ENDS_WITH)
|
||||
// We check that we don't have the crate list.
|
||||
assert-false: ".sidebar-elems .crate"
|
||||
assert-text: (".sidebar-elems > section ul > li:nth-child(1)", "Functions")
|
||||
@ -152,14 +171,14 @@ assert-property: (".sidebar", {"clientWidth": "200"})
|
||||
|
||||
// Checks that all.html and index.html have their sidebar link in the same place.
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
store-property: (".sidebar .location a", {
|
||||
store-property: (".sidebar .sidebar-crate h2 a", {
|
||||
"clientWidth": index_sidebar_width,
|
||||
"clientHeight": index_sidebar_height,
|
||||
"offsetTop": index_sidebar_y,
|
||||
"offsetLeft": index_sidebar_x,
|
||||
})
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/all.html"
|
||||
assert-property: (".sidebar .location a", {
|
||||
assert-property: (".sidebar .sidebar-crate h2 a", {
|
||||
"clientWidth": |index_sidebar_width|,
|
||||
"clientHeight": |index_sidebar_height|,
|
||||
"offsetTop": |index_sidebar_y|,
|
||||
|
@ -8,13 +8,13 @@ set-window-size: (600, 800)
|
||||
assert-property: ("html", {"scrollTop": "0"})
|
||||
|
||||
click: '//a[text() = "barbar" and @href="#5-7"]'
|
||||
assert-property: ("html", {"scrollTop": "149"})
|
||||
assert-property: ("html", {"scrollTop": "123"})
|
||||
click: '//a[text() = "bar" and @href="#28-36"]'
|
||||
assert-property: ("html", {"scrollTop": "180"})
|
||||
assert-property: ("html", {"scrollTop": "154"})
|
||||
click: '//a[text() = "sub_fn" and @href="#2-4"]'
|
||||
assert-property: ("html", {"scrollTop": "77"})
|
||||
assert-property: ("html", {"scrollTop": "51"})
|
||||
|
||||
// We now check that clicking on lines doesn't change the scroll
|
||||
// Extra information: the "sub_fn" function header is on line 1.
|
||||
click: '//*[@id="6"]'
|
||||
assert-property: ("html", {"scrollTop": "77"})
|
||||
assert-property: ("html", {"scrollTop": "51"})
|
||||
|
@ -89,9 +89,9 @@ assert-css: (".src-line-numbers", {"text-align": "right"})
|
||||
// do anything (and certainly not add a `#NaN` to the URL!).
|
||||
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
|
||||
// We use this assert-position to know where we will click.
|
||||
assert-position: ("//*[@id='1']", {"x": 88, "y": 112})
|
||||
assert-position: ("//*[@id='1']", {"x": 88, "y": 86})
|
||||
// We click on the left of the "1" anchor but still in the "src-line-number" `<pre>`.
|
||||
click: (87, 103)
|
||||
click: (87, 77)
|
||||
assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH)
|
||||
|
||||
// Checking the source code sidebar.
|
||||
@ -163,16 +163,16 @@ assert-css: ("nav.sub", {"flex-direction": "row"})
|
||||
// To check this, we maintain the invariant:
|
||||
//
|
||||
// offsetTop[nav.sub form] = offsetTop[#main-content] - offsetHeight[nav.sub form] - offsetTop[nav.sub form]
|
||||
assert-property: ("nav.sub form", {"offsetTop": 28, "offsetHeight": 34})
|
||||
assert-property: ("#main-content", {"offsetTop": 90})
|
||||
// 28 = 90 - 34 - 28
|
||||
assert-property: ("nav.sub form", {"offsetTop": 15, "offsetHeight": 34})
|
||||
assert-property: ("#main-content", {"offsetTop": 64})
|
||||
// 15 = 64 - 34 - 15
|
||||
|
||||
// Now do the same check on moderately-sized, tablet mobile.
|
||||
set-window-size: (700, 700)
|
||||
assert-css: ("nav.sub", {"flex-direction": "row"})
|
||||
assert-property: ("nav.sub form", {"offsetTop": 21, "offsetHeight": 34})
|
||||
assert-property: ("#main-content", {"offsetTop": 76})
|
||||
// 21 = 76 - 34 - 21
|
||||
assert-property: ("nav.sub form", {"offsetTop": 8, "offsetHeight": 34})
|
||||
assert-property: ("#main-content", {"offsetTop": 50})
|
||||
// 8 = 50 - 34 - 8
|
||||
|
||||
// Check the sidebar directory entries have a marker and spacing (tablet).
|
||||
store-property: ("#src-sidebar > .title", {
|
||||
@ -198,7 +198,12 @@ call-function: ("check-sidebar-dir-entry", {
|
||||
"y": |source_sidebar_title_y| + |source_sidebar_title_height| + 6,
|
||||
})
|
||||
|
||||
// The logo is not present on this page.
|
||||
assert-false: ".sub-logo-container > img"
|
||||
|
||||
// Check the staged-api page instead, which does.
|
||||
// Now we check that the logo has a bottom margin so it's not stuck to the search input.
|
||||
go-to: "file://" + |DOC_PATH| + "/src/staged_api/lib.rs.html"
|
||||
assert-css: (".sub-logo-container > img", {"margin-bottom": "8px"})
|
||||
store-property: (".sub-logo-container", {"clientHeight": logo_height})
|
||||
assert-position: (".search-form", {"y": |logo_height| + 8})
|
||||
|
@ -1,6 +1,8 @@
|
||||
#![feature(staged_api)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![allow(internal_features)]
|
||||
#![stable(feature = "some_feature", since = "1.3.5")]
|
||||
#![doc(rust_logo)]
|
||||
|
||||
#[stable(feature = "some_feature", since = "1.3.5")]
|
||||
pub struct Foo {}
|
||||
|
@ -2,4 +2,4 @@
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// @has 'foo/index.html' '//li[@class="version"]' 'Version <script>alert("hi")</script>'
|
||||
// @has 'foo/index.html' '//*[@class="version"]' '<script>alert("hi")</script>'
|
||||
|
7
tests/rustdoc/crate-version-extra.rs
Normal file
7
tests/rustdoc/crate-version-extra.rs
Normal file
@ -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)'
|
@ -1,3 +1,3 @@
|
||||
// compile-flags: --crate-version=1.3.37
|
||||
|
||||
// @has 'crate_version/index.html' '//*[@class="version"]' 'Version 1.3.37'
|
||||
// @has 'crate_version/index.html' '//*[@class="version"]' '1.3.37'
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Note: this test is paired with logo-class.rs.
|
||||
// @has logo_class_default/struct.SomeStruct.html '//*[@class="logo-container"]/img[@class="rust-logo"]' ''
|
||||
// @has src/logo_class_default/logo-class-default.rs.html '//*[@class="sub-logo-container"]/img[@class="rust-logo"]' ''
|
||||
// Note: this test is paired with logo-class.rs and logo-class-rust.rs.
|
||||
// @!has logo_class_default/struct.SomeStruct.html '//*[@class="logo-container"]/img' ''
|
||||
// @!has src/logo_class_default/logo-class-default.rs.html '//*[@class="sub-logo-container"]/img' ''
|
||||
pub struct SomeStruct;
|
||||
|
7
tests/rustdoc/logo-class-rust.rs
Normal file
7
tests/rustdoc/logo-class-rust.rs
Normal file
@ -0,0 +1,7 @@
|
||||
#![feature(rustdoc_internals)]
|
||||
#![allow(internal_features)]
|
||||
#![doc(rust_logo)]
|
||||
// Note: this test is paired with logo-class.rs and logo-class-default.rs.
|
||||
// @has logo_class_rust/struct.SomeStruct.html '//*[@class="logo-container"]/img[@class="rust-logo"]' ''
|
||||
// @has src/logo_class_rust/logo-class-rust.rs.html '//*[@class="sub-logo-container"]/img[@class="rust-logo"]' ''
|
||||
pub struct SomeStruct;
|
@ -1,6 +1,6 @@
|
||||
#![doc(html_logo_url =
|
||||
"https://raw.githubusercontent.com/sagebind/isahc/master/media/isahc.svg.png")]
|
||||
// Note: this test is paired with logo-class-default.rs.
|
||||
// Note: this test is paired with logo-class-default.rs and logo-class-rust.rs.
|
||||
|
||||
// @has logo_class/struct.SomeStruct.html '//*[@class="logo-container"]/img[@src="https://raw.githubusercontent.com/sagebind/isahc/master/media/isahc.svg.png"]' ''
|
||||
// @!has logo_class/struct.SomeStruct.html '//*[@class="logo-container"]/img[@class="rust-logo"]' ''
|
||||
|
@ -2,7 +2,8 @@
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
// @matches 'foo/index.html' '//h1' 'Crate foo'
|
||||
// @matches 'foo/index.html' '//h2[@class="location"]' 'Crate foo'
|
||||
// @matches 'foo/index.html' '//div[@class="sidebar-crate"]/h2/a' 'foo'
|
||||
// @count 'foo/index.html' '//h2[@class="location"]' 0
|
||||
|
||||
// @matches 'foo/foo_mod/index.html' '//h1' 'Module foo::foo_mod'
|
||||
// @matches 'foo/foo_mod/index.html' '//h2[@class="location"]' 'Module foo_mod'
|
||||
|
5
tests/ui/feature-gates/doc-rust-logo.rs
Normal file
5
tests/ui/feature-gates/doc-rust-logo.rs
Normal file
@ -0,0 +1,5 @@
|
||||
#![doc(rust_logo)]
|
||||
//~^ ERROR the `#[doc(rust_logo)]` attribute is used for Rust branding
|
||||
//! This is not an official rust crate
|
||||
|
||||
fn main() {}
|
12
tests/ui/feature-gates/doc-rust-logo.stderr
Normal file
12
tests/ui/feature-gates/doc-rust-logo.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0658]: the `#[doc(rust_logo)]` attribute is used for Rust branding
|
||||
--> $DIR/doc-rust-logo.rs:1:8
|
||||
|
|
||||
LL | #![doc(rust_logo)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #90418 <https://github.com/rust-lang/rust/issues/90418> for more information
|
||||
= help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
Loading…
Reference in New Issue
Block a user