Skip to content

Commit

Permalink
Auto merge of #47620 - GuillaumeGomez:multiple-themes, r=QuietMisdreavus
Browse files Browse the repository at this point in the history
Multiple themes for rustdoc

r? @QuietMisdreavus
  • Loading branch information
bors committed Jan 23, 2018
2 parents 48a7ea9 + 5b85044 commit 3a39b2a
Show file tree
Hide file tree
Showing 10 changed files with 603 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/librustdoc/externalfiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::str;
use html::markdown::{Markdown, RenderType};

#[derive(Clone)]
pub struct ExternalHtml{
pub struct ExternalHtml {
/// Content that will be included inline in the <head> section of a
/// rendered Markdown file or generated documentation
pub in_header: String,
Expand Down
21 changes: 18 additions & 3 deletions src/librustdoc/html/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

use std::fmt;
use std::io;
use std::path::PathBuf;

use externalfiles::ExternalHtml;

Expand All @@ -31,7 +32,7 @@ pub struct Page<'a> {

pub fn render<T: fmt::Display, S: fmt::Display>(
dst: &mut io::Write, layout: &Layout, page: &Page, sidebar: &S, t: &T,
css_file_extension: bool)
css_file_extension: bool, themes: &[PathBuf])
-> io::Result<()>
{
write!(dst,
Expand All @@ -47,8 +48,11 @@ r##"<!DOCTYPE html>
<title>{title}</title>
<link rel="stylesheet" type="text/css" href="{root_path}normalize.css">
<link rel="stylesheet" type="text/css" href="{root_path}rustdoc.css">
<link rel="stylesheet" type="text/css" href="{root_path}main.css">
<link rel="stylesheet" type="text/css" href="{root_path}rustdoc.css" id="mainThemeStyle">
{themes}
<link rel="stylesheet" type="text/css" href="{root_path}dark.css">
<link rel="stylesheet" type="text/css" href="{root_path}main.css" id="themeStyle">
<script src="{root_path}storage.js"></script>
{css_extension}
{favicon}
Expand All @@ -70,6 +74,11 @@ r##"<!DOCTYPE html>
{sidebar}
</nav>
<button id="theme-picker">
<img src="{root_path}brush.svg" width="18" alt="Pick another theme!">
<div id="theme-choices"></div>
</button>
<script src="{root_path}theme.js"></script>
<nav class="sub">
<form class="search-form js-only">
<div class="search-container">
Expand Down Expand Up @@ -176,6 +185,12 @@ r##"<!DOCTYPE html>
after_content = layout.external_html.after_content,
sidebar = *sidebar,
krate = layout.krate,
themes = themes.iter()
.filter_map(|t| t.file_stem())
.filter_map(|t| t.to_str())
.map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}">"#,
page.root_path, t))
.collect::<String>(),
)
}

Expand Down
82 changes: 76 additions & 6 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ pub struct SharedContext {
/// This flag indicates whether listings of modules (in the side bar and documentation itself)
/// should be ordered alphabetically or in order of appearance (in the source code).
pub sort_modules_alphabetically: bool,
/// Additional themes to be added to the generated docs.
pub themes: Vec<PathBuf>,
}

impl SharedContext {
Expand Down Expand Up @@ -219,6 +221,17 @@ impl Error {
}
}

macro_rules! try_none {
($e:expr, $file:expr) => ({
use std::io;
match $e {
Some(e) => e,
None => return Err(Error::new(io::Error::new(io::ErrorKind::Other, "not found"),
$file))
}
})
}

macro_rules! try_err {
($e:expr, $file:expr) => ({
match $e {
Expand Down Expand Up @@ -489,7 +502,8 @@ pub fn run(mut krate: clean::Crate,
renderinfo: RenderInfo,
render_type: RenderType,
sort_modules_alphabetically: bool,
deny_render_differences: bool) -> Result<(), Error> {
deny_render_differences: bool,
themes: Vec<PathBuf>) -> Result<(), Error> {
let src_root = match krate.src {
FileName::Real(ref p) => match p.parent() {
Some(p) => p.to_path_buf(),
Expand All @@ -513,6 +527,7 @@ pub fn run(mut krate: clean::Crate,
markdown_warnings: RefCell::new(vec![]),
created_dirs: RefCell::new(FxHashSet()),
sort_modules_alphabetically,
themes,
};

// If user passed in `--playground-url` arg, we fill in crate name here
Expand Down Expand Up @@ -859,12 +874,65 @@ fn write_shared(cx: &Context,
// Add all the static files. These may already exist, but we just
// overwrite them anyway to make sure that they're fresh and up-to-date.

write(cx.dst.join("main.js"),
include_bytes!("static/main.js"))?;
write(cx.dst.join("rustdoc.css"),
include_bytes!("static/rustdoc.css"))?;

// To avoid "main.css" to be overwritten, we'll first run over the received themes and only
// then we'll run over the "official" styles.
let mut themes: HashSet<String> = HashSet::new();

for entry in &cx.shared.themes {
let mut content = Vec::with_capacity(100000);

let mut f = try_err!(File::open(&entry), &entry);
try_err!(f.read_to_end(&mut content), &entry);
write(cx.dst.join(try_none!(entry.file_name(), &entry)), content.as_slice())?;
themes.insert(try_none!(try_none!(entry.file_stem(), &entry).to_str(), &entry).to_owned());
}

write(cx.dst.join("brush.svg"),
include_bytes!("static/brush.svg"))?;
write(cx.dst.join("main.css"),
include_bytes!("static/styles/main.css"))?;
include_bytes!("static/themes/main.css"))?;
themes.insert("main".to_owned());
write(cx.dst.join("dark.css"),
include_bytes!("static/themes/dark.css"))?;
themes.insert("dark".to_owned());

let mut themes: Vec<&String> = themes.iter().collect();
themes.sort();
// To avoid theme switch latencies as much as possible, we put everything theme related
// at the beginning of the html files into another js file.
write(cx.dst.join("theme.js"), format!(
r#"var themes = document.getElementById("theme-choices");
var themePicker = document.getElementById("theme-picker");
themePicker.onclick = function() {{
if (themes.style.display === "block") {{
themes.style.display = "none";
themePicker.style.borderBottomRightRadius = "3px";
themePicker.style.borderBottomLeftRadius = "3px";
}} else {{
themes.style.display = "block";
themePicker.style.borderBottomRightRadius = "0";
themePicker.style.borderBottomLeftRadius = "0";
}}
}};
[{}].forEach(function(item) {{
var div = document.createElement('div');
div.innerHTML = item;
div.onclick = function(el) {{
switchTheme(currentTheme, mainTheme, item);
}};
themes.appendChild(div);
}});
"#, themes.iter()
.map(|s| format!("\"{}\"", s))
.collect::<Vec<String>>()
.join(",")).as_bytes())?;

write(cx.dst.join("main.js"), include_bytes!("static/main.js"))?;
write(cx.dst.join("storage.js"), include_bytes!("static/storage.js"))?;

if let Some(ref css) = cx.shared.css_file_extension {
let out = cx.dst.join("theme.css");
try_err!(fs::copy(css, out), css);
Expand Down Expand Up @@ -1156,7 +1224,8 @@ impl<'a> SourceCollector<'a> {
};
layout::render(&mut w, &self.scx.layout,
&page, &(""), &Source(contents),
self.scx.css_file_extension.is_some())?;
self.scx.css_file_extension.is_some(),
&self.scx.themes)?;
w.flush()?;
self.scx.local_sources.insert(p.clone(), href);
Ok(())
Expand Down Expand Up @@ -1520,7 +1589,8 @@ impl Context {
layout::render(writer, &self.shared.layout, &page,
&Sidebar{ cx: self, item: it },
&Item{ cx: self, item: it },
self.shared.css_file_extension.is_some())?;
self.shared.css_file_extension.is_some(),
&self.shared.themes)?;
} else {
let mut url = self.root_path();
if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) {
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/html/static/brush.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 11 additions & 1 deletion src/librustdoc/html/static/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@
}
}
document.getElementsByTagName("body")[0].style.marginTop = '45px';
var themePicker = document.getElementById("theme-picker");
if (themePicker) {
themePicker.style.position = "fixed";
}
}

function hideSidebar() {
Expand All @@ -136,6 +140,10 @@
filler.remove();
}
document.getElementsByTagName("body")[0].style.marginTop = '';
var themePicker = document.getElementById("theme-picker");
if (themePicker) {
themePicker.style.position = "absolute";
}
}

// used for special search precedence
Expand Down Expand Up @@ -1532,7 +1540,9 @@
ul.appendChild(li);
}
div.appendChild(ul);
sidebar.appendChild(div);
if (sidebar) {
sidebar.appendChild(div);
}
}

block("primitive", "Primitive Types");
Expand Down
38 changes: 37 additions & 1 deletion src/librustdoc/html/static/rustdoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,8 @@ ul.item-list > li > .out-of-band {
}

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

.in-band, code {
Expand All @@ -376,6 +377,7 @@ h4 > code, h3 > code, .invisible > code {
margin: 0px;
padding: 0px;
display: inline-block;
max-width: calc(100% - 43px);
}

.in-band > code {
Expand Down Expand Up @@ -1140,3 +1142,37 @@ kbd {
border-radius: 3px;
box-shadow: inset 0 -1px 0;
}

#theme-picker {
position: absolute;
left: 211px;
top: 17px;
padding: 4px;
border: 1px solid;
border-radius: 3px;
cursor: pointer;
}

#theme-choices {
display: none;
position: absolute;
left: -1px;
top: 30px;
border: 1px solid;
border-radius: 3px;
z-index: 1;
}

#theme-choices > div {
border-top: 1px solid;
padding: 4px;
text-align: center;
}

@media (max-width: 700px) {
#theme-picker {
left: 109px;
top: 7px;
z-index: 1;
}
}
36 changes: 36 additions & 0 deletions src/librustdoc/html/static/storage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*!
* Copyright 2018 The Rust Project Developers. See the COPYRIGHT
* file at the top-level directory of this distribution and at
* http://rust-lang.org/COPYRIGHT.
*
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
* http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
* <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
* option. This file may not be copied, modified, or distributed
* except according to those terms.
*/

var currentTheme = document.getElementById("themeStyle");
var mainTheme = document.getElementById("mainThemeStyle");

function updateLocalStorage(name, value) {
if (typeof(Storage) !== "undefined") {
localStorage[name] = value;
} else {
// No Web Storage support so we do nothing
}
}

function getCurrentValue(name) {
if (typeof(Storage) !== "undefined" && localStorage[name] !== undefined) {
return localStorage[name];
}
return null;
}

function switchTheme(styleElem, mainStyleElem, newTheme) {
styleElem.href = mainStyleElem.href.replace("rustdoc.css", newTheme + ".css");
updateLocalStorage('theme', newTheme);
}

switchTheme(currentTheme, mainTheme, getCurrentValue('theme') || 'main');
Loading

0 comments on commit 3a39b2a

Please sign in to comment.