]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/html/layout.rs
Rollup merge of #91091 - ecstatic-morse:control-flow-enum-is, r=m-ou-se
[rust.git] / src / librustdoc / html / layout.rs
1 use std::path::PathBuf;
2
3 use rustc_data_structures::fx::FxHashMap;
4
5 use crate::error::Error;
6 use crate::externalfiles::ExternalHtml;
7 use crate::html::format::{Buffer, Print};
8 use crate::html::render::{ensure_trailing_slash, StylePath};
9
10 use serde::Serialize;
11
12 #[derive(Clone, Serialize)]
13 crate struct Layout {
14     crate logo: String,
15     crate favicon: String,
16     crate external_html: ExternalHtml,
17     crate default_settings: FxHashMap<String, String>,
18     crate krate: String,
19     /// The given user css file which allow to customize the generated
20     /// documentation theme.
21     crate css_file_extension: Option<PathBuf>,
22     /// If false, the `select` element to have search filtering by crates on rendered docs
23     /// won't be generated.
24     crate generate_search_filter: bool,
25     /// If true, then scrape-examples.js will be included in the output HTML file
26     crate scrape_examples_extension: bool,
27 }
28
29 #[derive(Serialize)]
30 crate struct Page<'a> {
31     crate title: &'a str,
32     crate css_class: &'a str,
33     crate root_path: &'a str,
34     crate static_root_path: Option<&'a str>,
35     crate description: &'a str,
36     crate keywords: &'a str,
37     crate resource_suffix: &'a str,
38     crate extra_scripts: &'a [&'a str],
39     crate static_extra_scripts: &'a [&'a str],
40 }
41
42 impl<'a> Page<'a> {
43     crate fn get_static_root_path(&self) -> &str {
44         self.static_root_path.unwrap_or(self.root_path)
45     }
46 }
47
48 #[derive(Serialize)]
49 struct PageLayout<'a> {
50     static_root_path: &'a str,
51     page: &'a Page<'a>,
52     layout: &'a Layout,
53     themes: Vec<String>,
54     sidebar: String,
55     content: String,
56     krate_with_trailing_slash: String,
57     crate rustdoc_version: &'a str,
58 }
59
60 crate fn render<T: Print, S: Print>(
61     templates: &tera::Tera,
62     layout: &Layout,
63     page: &Page<'_>,
64     sidebar: S,
65     t: T,
66     style_files: &[StylePath],
67 ) -> String {
68     let static_root_path = page.get_static_root_path();
69     let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string();
70     let mut themes: Vec<String> = style_files
71         .iter()
72         .map(StylePath::basename)
73         .collect::<Result<_, Error>>()
74         .unwrap_or_default();
75     themes.sort();
76     let rustdoc_version = rustc_interface::util::version_str().unwrap_or("unknown version");
77     let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
78     let sidebar = Buffer::html().to_display(sidebar);
79     let teractx = tera::Context::from_serialize(PageLayout {
80         static_root_path,
81         page,
82         layout,
83         themes,
84         sidebar,
85         content,
86         krate_with_trailing_slash,
87         rustdoc_version,
88     })
89     .unwrap();
90     templates.render("page.html", &teractx).unwrap()
91 }
92
93 crate fn redirect(url: &str) -> String {
94     // <script> triggers a redirect before refresh, so this is fine.
95     format!(
96         r##"<!DOCTYPE html>
97 <html lang="en">
98 <head>
99     <meta http-equiv="refresh" content="0;URL={url}">
100     <title>Redirection</title>
101 </head>
102 <body>
103     <p>Redirecting to <a href="{url}">{url}</a>...</p>
104     <script>location.replace("{url}" + location.search + location.hash);</script>
105 </body>
106 </html>"##,
107         url = url,
108     )
109 }