Skip to content

Commit 003b2bc

Browse files
Add possibility to have multiple themes
1 parent 3001ab1 commit 003b2bc

File tree

6 files changed

+537
-8
lines changed

6 files changed

+537
-8
lines changed

src/librustdoc/html/layout.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ r##"<!DOCTYPE html>
4747
<title>{title}</title>
4848
4949
<link rel="stylesheet" type="text/css" href="{root_path}normalize.css">
50-
<link rel="stylesheet" type="text/css" href="{root_path}rustdoc.css">
51-
<link rel="stylesheet" type="text/css" href="{root_path}main.css">
50+
<link rel="stylesheet" type="text/css" href="{root_path}rustdoc.css" id="mainThemeStyle">
51+
<link rel="stylesheet" type="text/css" href="{root_path}main.css" id="themeStyle">
5252
{css_extension}
5353
5454
{favicon}
@@ -70,6 +70,10 @@ r##"<!DOCTYPE html>
7070
{sidebar}
7171
</nav>
7272
73+
<div id="theme-picker">&#x1f58c;
74+
<div id="theme-choices"></div>
75+
</div>
76+
<script src="{root_path}theme.js"></script>
7377
<nav class="sub">
7478
<form class="search-form js-only">
7579
<div class="search-container">

src/librustdoc/html/render.rs

+78-4
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,17 @@ impl Error {
219219
}
220220
}
221221

222+
macro_rules! try_none {
223+
($e:expr, $file:expr) => ({
224+
use std::io;
225+
match $e {
226+
Some(e) => e,
227+
None => return Err(Error::new(io::Error::new(io::ErrorKind::Other, "not found"),
228+
$file))
229+
}
230+
})
231+
}
232+
222233
macro_rules! try_err {
223234
($e:expr, $file:expr) => ({
224235
match $e {
@@ -859,12 +870,75 @@ fn write_shared(cx: &Context,
859870
// Add all the static files. These may already exist, but we just
860871
// overwrite them anyway to make sure that they're fresh and up-to-date.
861872

862-
write(cx.dst.join("main.js"),
863-
include_bytes!("static/main.js"))?;
864873
write(cx.dst.join("rustdoc.css"),
865874
include_bytes!("static/rustdoc.css"))?;
866-
write(cx.dst.join("main.css"),
867-
include_bytes!("static/styles/main.css"))?;
875+
let path = cx.shared.src_root.join("../librustdoc/html/static/themes");
876+
let mut themes: Vec<String> = Vec::new();
877+
for entry in try_err!(fs::read_dir(path.clone()), &path) {
878+
let entry = try_err!(entry, &path);
879+
let mut content = Vec::with_capacity(100000);
880+
881+
let mut f = try_err!(File::open(entry.path()), &entry.path());
882+
try_err!(f.read_to_end(&mut content), &entry.path());
883+
write(cx.dst.join(entry.file_name()), content.as_slice())?;
884+
themes.push(try_none!(
885+
try_none!(entry.path().file_stem(), &entry.path()).to_str(),
886+
&entry.path()).to_owned());
887+
}
888+
themes.sort();
889+
// To avoid theme switch latencies as much as possible, we put everything theme related
890+
// at the beginning of the html files into another js file.
891+
write(cx.dst.join("theme.js"), format!(
892+
r#"var themes = document.getElementById("theme-choices");
893+
var themePicker = document.getElementById("theme-picker");
894+
themePicker.onclick = function() {{
895+
if (themes.style.display === "block") {{
896+
themes.style.display = "none";
897+
themePicker.style.borderBottomRightRadius = "3px";
898+
themePicker.style.borderBottomLeftRadius = "3px";
899+
}} else {{
900+
themes.style.display = "block";
901+
themePicker.style.borderBottomRightRadius = "0";
902+
themePicker.style.borderBottomLeftRadius = "0";
903+
}}
904+
}};
905+
var currentTheme = document.getElementById("themeStyle");
906+
var mainTheme = document.getElementById("mainThemeStyle");
907+
[{}].forEach(function(item) {{
908+
var div = document.createElement('div');
909+
div.innerHTML = item;
910+
div.onclick = function(el) {{
911+
switchTheme(currentTheme, mainTheme, item);
912+
}};
913+
themes.appendChild(div);
914+
}});
915+
916+
function updateLocalStorage(theme) {{
917+
if (typeof(Storage) !== "undefined") {{
918+
localStorage.theme = theme;
919+
}} else {{
920+
// No Web Storage support so we do nothing
921+
}}
922+
}}
923+
function switchTheme(styleElem, mainStyleElem, newTheme) {{
924+
styleElem.href = mainStyleElem.href.replace("rustdoc.css", newTheme + ".css");
925+
updateLocalStorage(newTheme);
926+
}}
927+
function getCurrentTheme() {{
928+
if (typeof(Storage) !== "undefined" && localStorage.theme !== undefined) {{
929+
return localStorage.theme;
930+
}}
931+
return "main";
932+
}}
933+
934+
switchTheme(currentTheme, mainTheme, getCurrentTheme());
935+
"#, themes.iter()
936+
.map(|s| format!("\"{}\"", s))
937+
.collect::<Vec<String>>()
938+
.join(",")).as_bytes())?;
939+
940+
write(cx.dst.join("main.js"), include_bytes!("static/main.js"))?;
941+
868942
if let Some(ref css) = cx.shared.css_file_extension {
869943
let out = cx.dst.join("theme.css");
870944
try_err!(fs::copy(css, out), css);

src/librustdoc/html/static/main.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@
122122
}
123123
}
124124
document.getElementsByTagName("body")[0].style.marginTop = '45px';
125+
var themePicker = document.getElementById("theme-picker");
126+
if (themePicker) {
127+
themePicker.style.position = "fixed";
128+
}
125129
}
126130

127131
function hideSidebar() {
@@ -136,6 +140,10 @@
136140
filler.remove();
137141
}
138142
document.getElementsByTagName("body")[0].style.marginTop = '';
143+
var themePicker = document.getElementById("theme-picker");
144+
if (themePicker) {
145+
themePicker.style.position = "absolute";
146+
}
139147
}
140148

141149
// used for special search precedence
@@ -1532,7 +1540,9 @@
15321540
ul.appendChild(li);
15331541
}
15341542
div.appendChild(ul);
1535-
sidebar.appendChild(div);
1543+
if (sidebar) {
1544+
sidebar.appendChild(div);
1545+
}
15361546
}
15371547

15381548
block("primitive", "Primitive Types");

src/librustdoc/html/static/rustdoc.css

+37-1
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,8 @@ ul.item-list > li > .out-of-band {
360360
}
361361

362362
h4 > code, h3 > code, .invisible > code {
363-
position: inherit;
363+
max-width: calc(100% - 41px);
364+
display: block;
364365
}
365366

366367
.in-band, code {
@@ -376,6 +377,7 @@ h4 > code, h3 > code, .invisible > code {
376377
margin: 0px;
377378
padding: 0px;
378379
display: inline-block;
380+
max-width: calc(100% - 43px);
379381
}
380382

381383
.in-band > code {
@@ -1140,3 +1142,37 @@ kbd {
11401142
border-radius: 3px;
11411143
box-shadow: inset 0 -1px 0;
11421144
}
1145+
1146+
#theme-picker {
1147+
position: absolute;
1148+
left: 211px;
1149+
top: 17px;
1150+
padding: 4px;
1151+
border: 1px solid;
1152+
border-radius: 3px;
1153+
cursor: pointer;
1154+
}
1155+
1156+
#theme-choices {
1157+
display: none;
1158+
position: absolute;
1159+
left: -1px;
1160+
top: 30px;
1161+
border: 1px solid;
1162+
border-radius: 3px;
1163+
z-index: 1;
1164+
}
1165+
1166+
#theme-choices > div {
1167+
border-top: 1px solid;
1168+
padding: 4px;
1169+
text-align: center;
1170+
}
1171+
1172+
@media (max-width: 700px) {
1173+
#theme-picker {
1174+
left: 109px;
1175+
top: 7px;
1176+
z-index: 1;
1177+
}
1178+
}

0 commit comments

Comments
 (0)