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