rust/src/librustdoc/html/layout.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

139 lines
4.4 KiB
Rust
Raw Normal View History

2018-01-23 00:45:34 +01:00
use std::path::PathBuf;
2024-07-18 20:56:36 +02:00
use rinja::Template;
use rustc_data_structures::fx::FxIndexMap;
2020-12-31 23:25:30 -05:00
use super::static_files::{STATIC_FILES, StaticFiles};
2019-02-23 16:40:07 +09:00
use crate::externalfiles::ExternalHtml;
2019-08-31 09:07:29 -04:00
use crate::html::format::{Buffer, Print};
use crate::html::render::{StylePath, ensure_trailing_slash};
2019-01-31 15:42:45 +01:00
2022-01-03 21:16:05 +01:00
#[derive(Clone)]
pub(crate) struct Layout {
pub(crate) logo: String,
pub(crate) favicon: String,
pub(crate) external_html: ExternalHtml,
pub(crate) default_settings: FxIndexMap<String, String>,
pub(crate) krate: String,
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.
2023-09-18 11:59:49 -07:00
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>,
2021-10-01 13:05:35 -07:00
/// If true, then scrape-examples.js will be included in the output HTML file
pub(crate) scrape_examples_extension: bool,
}
pub(crate) struct Page<'a> {
pub(crate) title: &'a str,
pub(crate) css_class: &'a str,
pub(crate) root_path: &'a str,
pub(crate) static_root_path: Option<&'a str>,
pub(crate) description: &'a str,
pub(crate) resource_suffix: &'a str,
pub(crate) rust_logo: bool,
}
2024-11-27 15:44:10 +01:00
impl Page<'_> {
pub(crate) fn get_static_root_path(&self) -> String {
match self.static_root_path {
Some(s) => s.to_string(),
None => format!("{}static.files/", self.root_path),
}
}
}
2022-01-03 21:16:05 +01:00
#[derive(Template)]
#[template(path = "page.html")]
struct PageLayout<'a> {
static_root_path: String,
page: &'a Page<'a>,
layout: &'a Layout,
files: &'static StaticFiles,
themes: Vec<String>,
sidebar: String,
content: 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) use crate::html::render::sidebar::filters;
pub(crate) fn render<T: Print, S: Print>(
2018-12-20 13:28:55 +01:00
layout: &Layout,
2019-02-23 16:40:07 +09:00
page: &Page<'_>,
sidebar: S,
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();
// 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 content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
let sidebar = Buffer::html().to_display(sidebar);
PageLayout {
static_root_path,
page,
layout,
files: &STATIC_FILES,
themes,
sidebar,
content,
display_krate,
display_krate_with_trailing_slash,
display_krate_version_number,
display_krate_version_extra,
rust_channel: *crate::clean::utils::DOC_CHANNEL,
rustdoc_version,
}
.render()
.unwrap()
}
pub(crate) fn redirect(url: &str) -> String {
// <script> triggers a redirect before refresh, so this is fine.
format!(
r##"<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="refresh" content="0;URL={url}">
<title>Redirection</title>
</head>
<body>
<p>Redirecting to <a href="{url}">{url}</a>...</p>
<script>location.replace("{url}" + location.search + location.hash);</script>
</body>
</html>"##,
url = url,
)
}