]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2013 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | use std::fmt; | |
c34b1796 | 12 | use std::io; |
1a4d82fc JJ |
13 | |
14 | use externalfiles::ExternalHtml; | |
15 | ||
16 | #[derive(Clone)] | |
17 | pub struct Layout { | |
18 | pub logo: String, | |
19 | pub favicon: String, | |
20 | pub external_html: ExternalHtml, | |
21 | pub krate: String, | |
1a4d82fc JJ |
22 | } |
23 | ||
24 | pub struct Page<'a> { | |
25 | pub title: &'a str, | |
9e0c209e | 26 | pub css_class: &'a str, |
1a4d82fc JJ |
27 | pub root_path: &'a str, |
28 | pub description: &'a str, | |
54a0048b | 29 | pub keywords: &'a str, |
1a4d82fc JJ |
30 | } |
31 | ||
85aaf69f | 32 | pub fn render<T: fmt::Display, S: fmt::Display>( |
54a0048b SL |
33 | dst: &mut io::Write, layout: &Layout, page: &Page, sidebar: &S, t: &T, |
34 | css_file_extension: bool) | |
c34b1796 | 35 | -> io::Result<()> |
1a4d82fc JJ |
36 | { |
37 | write!(dst, | |
38 | r##"<!DOCTYPE html> | |
39 | <html lang="en"> | |
40 | <head> | |
41 | <meta charset="utf-8"> | |
42 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
43 | <meta name="generator" content="rustdoc"> | |
44 | <meta name="description" content="{description}"> | |
45 | <meta name="keywords" content="{keywords}"> | |
46 | ||
47 | <title>{title}</title> | |
48 | ||
92a42be0 | 49 | <link rel="stylesheet" type="text/css" href="{root_path}rustdoc.css"> |
1a4d82fc | 50 | <link rel="stylesheet" type="text/css" href="{root_path}main.css"> |
54a0048b | 51 | {css_extension} |
1a4d82fc JJ |
52 | |
53 | {favicon} | |
54 | {in_header} | |
55 | </head> | |
56 | <body class="rustdoc"> | |
57 | <!--[if lte IE 8]> | |
58 | <div class="warning"> | |
59 | This old browser is unsupported and will most likely display funky | |
60 | things. | |
61 | </div> | |
62 | <![endif]--> | |
63 | ||
64 | {before_content} | |
65 | ||
e9174d1e | 66 | <nav class="sidebar"> |
1a4d82fc JJ |
67 | {logo} |
68 | {sidebar} | |
e9174d1e | 69 | </nav> |
1a4d82fc JJ |
70 | |
71 | <nav class="sub"> | |
72 | <form class="search-form js-only"> | |
73 | <div class="search-container"> | |
74 | <input class="search-input" name="search" | |
75 | autocomplete="off" | |
c1a9b12d | 76 | placeholder="Click or press ‘S’ to search, ‘?’ for more options…" |
1a4d82fc JJ |
77 | type="search"> |
78 | </div> | |
79 | </form> | |
80 | </nav> | |
81 | ||
9e0c209e | 82 | <section id='main' class="content {css_class}">{content}</section> |
1a4d82fc JJ |
83 | <section id='search' class="content hidden"></section> |
84 | ||
85 | <section class="footer"></section> | |
86 | ||
e9174d1e | 87 | <aside id="help" class="hidden"> |
c1a9b12d | 88 | <div> |
e9174d1e SL |
89 | <h1 class="hidden">Help</h1> |
90 | ||
c1a9b12d | 91 | <div class="shortcuts"> |
e9174d1e | 92 | <h2>Keyboard Shortcuts</h2> |
c1a9b12d SL |
93 | |
94 | <dl> | |
95 | <dt>?</dt> | |
96 | <dd>Show this help dialog</dd> | |
97 | <dt>S</dt> | |
98 | <dd>Focus the search field</dd> | |
99 | <dt>⇤</dt> | |
100 | <dd>Move up in search results</dd> | |
101 | <dt>⇥</dt> | |
102 | <dd>Move down in search results</dd> | |
103 | <dt>⏎</dt> | |
104 | <dd>Go to active search result</dd> | |
a7813a04 XL |
105 | <dt>+</dt> |
106 | <dd>Collapse/expand all sections</dd> | |
c1a9b12d SL |
107 | </dl> |
108 | </div> | |
109 | ||
110 | <div class="infos"> | |
e9174d1e | 111 | <h2>Search Tricks</h2> |
c1a9b12d SL |
112 | |
113 | <p> | |
114 | Prefix searches with a type followed by a colon (e.g. | |
115 | <code>fn:</code>) to restrict the search to a given type. | |
116 | </p> | |
117 | ||
118 | <p> | |
119 | Accepted types are: <code>fn</code>, <code>mod</code>, | |
120 | <code>struct</code>, <code>enum</code>, | |
e9174d1e SL |
121 | <code>trait</code>, <code>type</code>, <code>macro</code>, |
122 | and <code>const</code>. | |
c1a9b12d SL |
123 | </p> |
124 | ||
125 | <p> | |
126 | Search functions by type signature (e.g. | |
7453a54e | 127 | <code>vec -> usize</code> or <code>* -> vec</code>) |
c1a9b12d SL |
128 | </p> |
129 | </div> | |
1a4d82fc | 130 | </div> |
e9174d1e | 131 | </aside> |
1a4d82fc JJ |
132 | |
133 | {after_content} | |
134 | ||
135 | <script> | |
136 | window.rootPath = "{root_path}"; | |
137 | window.currentCrate = "{krate}"; | |
1a4d82fc JJ |
138 | </script> |
139 | <script src="{root_path}jquery.js"></script> | |
140 | <script src="{root_path}main.js"></script> | |
92a42be0 | 141 | <script defer src="{root_path}search-index.js"></script> |
1a4d82fc JJ |
142 | </body> |
143 | </html>"##, | |
54a0048b SL |
144 | css_extension = if css_file_extension { |
145 | format!("<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}theme.css\">", | |
146 | root_path = page.root_path) | |
147 | } else { | |
148 | "".to_owned() | |
149 | }, | |
1a4d82fc JJ |
150 | content = *t, |
151 | root_path = page.root_path, | |
9e0c209e | 152 | css_class = page.css_class, |
9346a6ac | 153 | logo = if layout.logo.is_empty() { |
1a4d82fc JJ |
154 | "".to_string() |
155 | } else { | |
156 | format!("<a href='{}{}/index.html'>\ | |
7453a54e | 157 | <img src='{}' alt='logo' width='100'></a>", |
1a4d82fc JJ |
158 | page.root_path, layout.krate, |
159 | layout.logo) | |
160 | }, | |
161 | title = page.title, | |
162 | description = page.description, | |
163 | keywords = page.keywords, | |
9346a6ac | 164 | favicon = if layout.favicon.is_empty() { |
1a4d82fc JJ |
165 | "".to_string() |
166 | } else { | |
167 | format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon) | |
168 | }, | |
169 | in_header = layout.external_html.in_header, | |
170 | before_content = layout.external_html.before_content, | |
171 | after_content = layout.external_html.after_content, | |
172 | sidebar = *sidebar, | |
173 | krate = layout.krate, | |
1a4d82fc JJ |
174 | ) |
175 | } | |
176 | ||
c34b1796 | 177 | pub fn redirect(dst: &mut io::Write, url: &str) -> io::Result<()> { |
1a4d82fc JJ |
178 | // <script> triggers a redirect before refresh, so this is fine. |
179 | write!(dst, | |
180 | r##"<!DOCTYPE html> | |
181 | <html lang="en"> | |
182 | <head> | |
183 | <meta http-equiv="refresh" content="0;URL={url}"> | |
184 | </head> | |
185 | <body> | |
186 | <p>Redirecting to <a href="{url}">{url}</a>...</p> | |
187 | <script>location.replace("{url}" + location.search + location.hash);</script> | |
188 | </body> | |
189 | </html>"##, | |
190 | url = url, | |
191 | ) | |
192 | } |