Skip to content

Commit f2ad3c3

Browse files
Add rustdoc settings menu
1 parent 9379bcd commit f2ad3c3

File tree

9 files changed

+238
-26
lines changed

9 files changed

+238
-26
lines changed

src/librustdoc/html/layout.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
8585
autocomplete=\"off\" \
8686
placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
8787
type=\"search\">\
88+
<a id=\"settings-menu\" href=\"{root_path}settings.html\">\
89+
<img src=\"{root_path}wheel{suffix}.svg\" width=\"18\" alt=\"Change settings\">\
90+
</a>\
8891
</div>\
8992
</form>\
9093
</nav>\
@@ -181,9 +184,10 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
181184
themes = themes.iter()
182185
.filter_map(|t| t.file_stem())
183186
.filter_map(|t| t.to_str())
184-
.map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}">"#,
187+
.map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}{}.css">"#,
185188
page.root_path,
186-
t.replace(".css", &format!("{}.css", page.resource_suffix))))
189+
t,
190+
page.resource_suffix))
187191
.collect::<String>(),
188192
suffix=page.resource_suffix,
189193
)

src/librustdoc/html/render.rs

+74-3
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,8 @@ fn write_shared(cx: &Context,
742742

743743
write(cx.dst.join(&format!("rustdoc{}.css", cx.shared.resource_suffix)),
744744
include_bytes!("static/rustdoc.css"))?;
745+
write(cx.dst.join(&format!("settings{}.css", cx.shared.resource_suffix)),
746+
include_bytes!("static/settings.css"))?;
745747

746748
// To avoid "light.css" to be overwritten, we'll first run over the received themes and only
747749
// then we'll run over the "official" styles.
@@ -761,6 +763,8 @@ fn write_shared(cx: &Context,
761763

762764
write(cx.dst.join(&format!("brush{}.svg", cx.shared.resource_suffix)),
763765
include_bytes!("static/brush.svg"))?;
766+
write(cx.dst.join(&format!("wheel{}.svg", cx.shared.resource_suffix)),
767+
include_bytes!("static/wheel.svg"))?;
764768
write(cx.dst.join(&format!("light{}.css", cx.shared.resource_suffix)),
765769
include_bytes!("static/themes/light.css"))?;
766770
themes.insert("light".to_owned());
@@ -794,8 +798,7 @@ themePicker.onclick = function() {{
794798
switchTheme(currentTheme, mainTheme, item);
795799
}};
796800
themes.appendChild(but);
797-
}});
798-
"#,
801+
}});"#,
799802
themes.iter()
800803
.map(|s| format!("\"{}\"", s))
801804
.collect::<Vec<String>>()
@@ -804,6 +807,8 @@ themePicker.onclick = function() {{
804807

805808
write(cx.dst.join(&format!("main{}.js", cx.shared.resource_suffix)),
806809
include_bytes!("static/main.js"))?;
810+
write(cx.dst.join(&format!("settings{}.js", cx.shared.resource_suffix)),
811+
include_bytes!("static/settings.js"))?;
807812

808813
{
809814
let mut data = format!("var resourcesSuffix = \"{}\";\n",
@@ -1503,6 +1508,51 @@ impl fmt::Display for AllTypes {
15031508
}
15041509
}
15051510

1511+
#[derive(Debug)]
1512+
struct Settings<'a> {
1513+
// (id, explanation, default value)
1514+
settings: Vec<(&'static str, &'static str, bool)>,
1515+
root_path: &'a str,
1516+
suffix: &'a str,
1517+
}
1518+
1519+
impl<'a> Settings<'a> {
1520+
pub fn new(root_path: &'a str, suffix: &'a str) -> Settings<'a> {
1521+
Settings {
1522+
settings: vec![
1523+
("item-declarations", "Auto-hide item declarations.", true),
1524+
("item-attributes", "Auto-hide item attributes.", true),
1525+
],
1526+
root_path,
1527+
suffix,
1528+
}
1529+
}
1530+
}
1531+
1532+
impl<'a> fmt::Display for Settings<'a> {
1533+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1534+
write!(f,
1535+
"<h1 class='fqn'>\
1536+
<span class='in-band'>Rustdoc settings</span>\
1537+
</h1>\
1538+
<div class='settings'>{}</div>\
1539+
<script src='{}settings{}.js'></script>",
1540+
self.settings.iter()
1541+
.map(|(id, text, enabled)| {
1542+
format!("<div class='setting-line'>\
1543+
<label class='toggle'>\
1544+
<input type='checkbox' id='{}' {}>\
1545+
<span class='slider'></span>\
1546+
</label>\
1547+
<div>{}</div>\
1548+
</div>", id, if *enabled { " checked" } else { "" }, text)
1549+
})
1550+
.collect::<String>(),
1551+
self.root_path,
1552+
self.suffix)
1553+
}
1554+
}
1555+
15061556
impl Context {
15071557
/// String representation of how to get back to the root path of the 'doc/'
15081558
/// folder in terms of a relative URL.
@@ -1546,6 +1596,8 @@ impl Context {
15461596
};
15471597
let final_file = self.dst.join(&krate.name)
15481598
.join("all.html");
1599+
let settings_file = self.dst.join("settings.html");
1600+
15491601
let crate_name = krate.name.clone();
15501602
item.name = Some(krate.name);
15511603

@@ -1567,7 +1619,7 @@ impl Context {
15671619
if !root_path.ends_with('/') {
15681620
root_path.push('/');
15691621
}
1570-
let page = layout::Page {
1622+
let mut page = layout::Page {
15711623
title: "List of all items in this crate",
15721624
css_class: "mod",
15731625
root_path: "../",
@@ -1590,6 +1642,25 @@ impl Context {
15901642
self.shared.css_file_extension.is_some(),
15911643
&self.shared.themes),
15921644
&final_file);
1645+
1646+
// If the file already exists, no need to generate it again...
1647+
if !settings_file.is_file() {
1648+
let settings = Settings::new("./", &self.shared.resource_suffix);
1649+
page.title = "Rustdoc settings";
1650+
page.description = "Settings of Rustdoc";
1651+
page.root_path = "./";
1652+
1653+
let mut w = BufWriter::new(try_err!(File::create(&settings_file), &settings_file));
1654+
let mut themes = self.shared.themes.clone();
1655+
let sidebar = "<p class='location'>Settings</p><div class='sidebar-elems'>".to_owned();
1656+
themes.push(PathBuf::from("settings.css"));
1657+
try_err!(layout::render(&mut w, &self.shared.layout,
1658+
&page, &sidebar, &settings,
1659+
self.shared.css_file_extension.is_some(),
1660+
&themes),
1661+
&settings_file);
1662+
}
1663+
15931664
Ok(())
15941665
}
15951666

src/librustdoc/html/static/main.js

+11-15
Original file line numberDiff line numberDiff line change
@@ -77,19 +77,13 @@
7777
return false;
7878
}
7979
var end = start + className.length;
80-
if (end < elemClass.length && elemClass[end] !== ' ') {
81-
return false;
82-
}
83-
return true;
80+
return !(end < elemClass.length && elemClass[end] !== ' ');
8481
}
8582
if (start > 0 && elemClass[start - 1] !== ' ') {
8683
return false;
8784
}
8885
var end = start + className.length;
89-
if (end < elemClass.length && elemClass[end] !== ' ') {
90-
return false;
91-
}
92-
return true;
86+
return !(end < elemClass.length && elemClass[end] !== ' ');
9387
}
9488
return false;
9589
}
@@ -320,7 +314,7 @@
320314
} else if (ev.target.tagName === 'SPAN' && hasClass(ev.target.parentNode, 'line-numbers')) {
321315
var prev_id = 0;
322316

323-
var set_fragment = function (name) {
317+
var set_fragment = function(name) {
324318
if (browserSupportsHistoryApi()) {
325319
history.replaceState(null, null, '#' + name);
326320
window.hashchange();
@@ -835,7 +829,7 @@
835829
query.search = val;
836830
// searching by type
837831
} else if (val.search("->") > -1) {
838-
var trimmer = function (s) { return s.trim(); };
832+
var trimmer = function(s) { return s.trim(); };
839833
var parts = val.split("->").map(trimmer);
840834
var input = parts[0];
841835
// sort inputs so that order does not matter
@@ -1547,7 +1541,7 @@
15471541
startSearch();
15481542

15491543
// Draw a convenient sidebar of known crates if we have a listing
1550-
if (rootPath === '../') {
1544+
if (rootPath === '../' || rootPath === "./") {
15511545
var sidebar = document.getElementsByClassName('sidebar-elems')[0];
15521546
if (sidebar) {
15531547
var div = document.createElement('div');
@@ -1566,11 +1560,11 @@
15661560
crates.sort();
15671561
for (var i = 0; i < crates.length; ++i) {
15681562
var klass = 'crate';
1569-
if (crates[i] === window.currentCrate) {
1563+
if (rootPath !== "./" && crates[i] === window.currentCrate) {
15701564
klass += ' current';
15711565
}
15721566
var link = document.createElement('a');
1573-
link.href = '../' + crates[i] + '/index.html';
1567+
link.href = rootPath + crates[i] + '/index.html';
15741568
link.title = rawSearchIndex[crates[i]].doc;
15751569
link.className = klass;
15761570
link.textContent = crates[i];
@@ -1947,7 +1941,7 @@
19471941
otherMessage = '&nbsp;Show&nbsp;type&nbsp;declaration';
19481942
}
19491943
e.parentNode.insertBefore(createToggle(otherMessage), e);
1950-
if (otherMessage) {
1944+
if (otherMessage && getCurrentValue('rustdoc-item-declarations') !== "false") {
19511945
collapseDocs(e.previousSibling.childNodes[0], "toggle");
19521946
}
19531947
}
@@ -2017,7 +2011,9 @@
20172011
onEach(document.getElementById('main').getElementsByTagName('pre'), function(e) {
20182012
onEach(e.getElementsByClassName('attributes'), function(i_e) {
20192013
i_e.parentNode.insertBefore(createToggleWrapper(), i_e);
2020-
collapseDocs(i_e.previousSibling.childNodes[0], "toggle");
2014+
if (getCurrentValue("rustdoc-item-attributes") !== "false") {
2015+
collapseDocs(i_e.previousSibling.childNodes[0], "toggle");
2016+
}
20212017
});
20222018
});
20232019

src/librustdoc/html/static/rustdoc.css

+17-2
Original file line numberDiff line numberDiff line change
@@ -548,8 +548,16 @@ a {
548548

549549
.block a.current.crate { font-weight: 500; }
550550

551+
.search-container {
552+
position: relative;
553+
}
554+
.search-container > .top-button {
555+
position: absolute;
556+
right: 0;
557+
top: 10px;
558+
}
551559
.search-input {
552-
width: 100%;
560+
width: calc(100% - 34px);
553561
/* Override Normalize.css: we have margins and do
554562
not want to overflow - the `moz` attribute is necessary
555563
until Firefox 29, too early to drop at this point */
@@ -1224,7 +1232,14 @@ kbd {
12241232
outline: none;
12251233
}
12261234

1227-
#theme-picker {
1235+
#settings-menu {
1236+
position: absolute;
1237+
right: 0;
1238+
top: 10px;
1239+
outline: none;
1240+
}
1241+
1242+
#theme-picker, #settings-menu {
12281243
padding: 4px;
12291244
width: 27px;
12301245
height: 29px;
+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* Copyright 2018 The Rust Project Developers. See the COPYRIGHT
3+
* file at the top-level directory of this distribution and at
4+
* http://rust-lang.org/COPYRIGHT.
5+
*
6+
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
7+
* http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8+
* <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
9+
* option. This file may not be copied, modified, or distributed
10+
* except according to those terms.
11+
*/
12+
13+
.setting-line {
14+
padding: 5px;
15+
}
16+
17+
.setting-line > div {
18+
max-width: calc(100% - 74px);
19+
display: inline-block;
20+
vertical-align: top;
21+
font-size: 17px;
22+
padding-top: 2px;
23+
}
24+
25+
.toggle {
26+
position: relative;
27+
display: inline-block;
28+
width: 45px;
29+
height: 27px;
30+
margin-right: 20px;
31+
}
32+
33+
.toggle input {
34+
display: none;
35+
}
36+
37+
.slider {
38+
position: absolute;
39+
cursor: pointer;
40+
top: 0;
41+
left: 0;
42+
right: 0;
43+
bottom: 0;
44+
background-color: #ccc;
45+
-webkit-transition: .3s;
46+
transition: .3s;
47+
}
48+
49+
.slider:before {
50+
position: absolute;
51+
content: "";
52+
height: 19px;
53+
width: 19px;
54+
left: 4px;
55+
bottom: 4px;
56+
background-color: white;
57+
-webkit-transition: .3s;
58+
transition: .3s;
59+
}
60+
61+
input:checked + .slider {
62+
background-color: #2196F3;
63+
}
64+
65+
input:focus + .slider {
66+
box-shadow: 0 0 1px #2196F3;
67+
}
68+
69+
input:checked + .slider:before {
70+
-webkit-transform: translateX(19px);
71+
-ms-transform: translateX(19px);
72+
transform: translateX(19px);
73+
}
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*!
2+
* Copyright 2018 The Rust Project Developers. See the COPYRIGHT
3+
* file at the top-level directory of this distribution and at
4+
* http://rust-lang.org/COPYRIGHT.
5+
*
6+
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
7+
* http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8+
* <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
9+
* option. This file may not be copied, modified, or distributed
10+
* except according to those terms.
11+
*/
12+
13+
(function () {
14+
function changeSetting(settingName, isEnabled) {
15+
updateLocalStorage('rustdoc-' + settingName, isEnabled);
16+
}
17+
18+
function getSettingValue(settingName) {
19+
return getCurrentValue('rustdoc-' + settingName);
20+
}
21+
22+
function replaceLogoHref() {
23+
var elem = document.getElementsByClassName("sidebar-menu");
24+
if (elem && elem.length > 0) {
25+
elem[0].nextElementSibling.setAttribute('href', 'javascript:void');
26+
}
27+
}
28+
29+
function setEvents() {
30+
var elems = document.getElementsByClassName("slider");
31+
if (!elems || elems.length === 0) {
32+
return;
33+
}
34+
for (var i = 0; i < elems.length; ++i) {
35+
var toggle = elems[i].previousElementSibling;
36+
var settingId = toggle.id;
37+
var settingValue = getSettingValue(settingId);
38+
if (settingValue !== null) {
39+
toggle.checked = settingValue === "true";
40+
}
41+
toggle.onchange = function() {
42+
changeSetting(this.id, this.checked);
43+
};
44+
}
45+
}
46+
47+
// To remove possibility to come back to "something" by clicking on the logo.
48+
replaceLogoHref();
49+
setEvents();
50+
})();

0 commit comments

Comments
 (0)