Skip to content

Commit d716d1c

Browse files
authored
Rollup merge of rust-lang#71237 - Cldfire:rustdoc-ayu-theme, r=GuilliaumeGomez
Add Ayu theme to rustdoc This is a port of a theme I maintain (https://github.com/Cldfire/ayu-rs) to the native rustdoc theme system. [Ayu](https://github.com/dempfi/ayu) (dark) is a richly-colored dark theme that many people enjoy using across a wide variety of environments. Corresponds to the Ayu theme in [mdBook](https://github.com/rust-lang/mdBook). Some screenshots: ![image](https://user-images.githubusercontent.com/13814214/79547087-6c935780-8061-11ea-8a33-38e9472e9fec.png) ![image](https://user-images.githubusercontent.com/13814214/79547150-8339ae80-8061-11ea-97be-9e13a8b275d7.png) ![image](https://user-images.githubusercontent.com/13814214/79547221-98164200-8061-11ea-9649-9b11ccbb33e3.png) ![image](https://user-images.githubusercontent.com/13814214/79547310-b419e380-8061-11ea-9965-d4f90b2280ab.png) ![image](https://user-images.githubusercontent.com/13814214/79547443-e7f50900-8061-11ea-8872-06d74010691e.png) Note that this pull request also makes some small code changes to allow for disabling theme stylesheets, preventing the rules from all the different themes from conflicting with one another. The only stylesheet that is not disabled is `light.css`; the theming system (quite hackily) switches themes by changing the href on this stylesheet and so permanently disabling all the others works perfectly fine.
2 parents c724b67 + 8c45cf8 commit d716d1c

File tree

6 files changed

+647
-43
lines changed

6 files changed

+647
-43
lines changed

src/librustdoc/config.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::core::new_handler;
2020
use crate::externalfiles::ExternalHtml;
2121
use crate::html;
2222
use crate::html::markdown::IdMap;
23+
use crate::html::render::StylePath;
2324
use crate::html::static_files;
2425
use crate::opts;
2526
use crate::passes::{self, Condition, DefaultPassOption};
@@ -207,7 +208,7 @@ pub struct RenderOptions {
207208
pub sort_modules_alphabetically: bool,
208209
/// List of themes to extend the docs with. Original argument name is included to assist in
209210
/// displaying errors if it fails a theme check.
210-
pub themes: Vec<PathBuf>,
211+
pub themes: Vec<StylePath>,
211212
/// If present, CSS file that contains rules to add to the default CSS.
212213
pub extension_css: Option<PathBuf>,
213214
/// A map of crate names to the URL to use instead of querying the crate's `html_root_url`.
@@ -410,7 +411,7 @@ impl Options {
410411
))
411412
.emit();
412413
}
413-
themes.push(theme_file);
414+
themes.push(StylePath { path: theme_file, disabled: true });
414415
}
415416
}
416417

src/librustdoc/html/layout.rs

+14-11
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::path::PathBuf;
33
use crate::externalfiles::ExternalHtml;
44
use crate::html::escape::Escape;
55
use crate::html::format::{Buffer, Print};
6-
use crate::html::render::ensure_trailing_slash;
6+
use crate::html::render::{ensure_trailing_slash, StylePath};
77

88
#[derive(Clone)]
99
pub struct Layout {
@@ -36,7 +36,7 @@ pub fn render<T: Print, S: Print>(
3636
page: &Page<'_>,
3737
sidebar: S,
3838
t: T,
39-
themes: &[PathBuf],
39+
style_files: &[StylePath],
4040
) -> String {
4141
let static_root_path = page.static_root_path.unwrap_or(page.root_path);
4242
format!(
@@ -52,10 +52,7 @@ pub fn render<T: Print, S: Print>(
5252
<link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
5353
<link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
5454
id=\"mainThemeStyle\">\
55-
{themes}\
56-
<link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}dark{suffix}.css\">\
57-
<link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}light{suffix}.css\" \
58-
id=\"themeStyle\">\
55+
{style_files}\
5956
<script src=\"{static_root_path}storage{suffix}.js\"></script>\
6057
<noscript><link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\"></noscript>\
6158
{css_extension}\
@@ -172,13 +169,19 @@ pub fn render<T: Print, S: Print>(
172169
after_content = layout.external_html.after_content,
173170
sidebar = Buffer::html().to_display(sidebar),
174171
krate = layout.krate,
175-
themes = themes
172+
style_files = style_files
176173
.iter()
177-
.filter_map(|t| t.file_stem())
178-
.filter_map(|t| t.to_str())
174+
.filter_map(|t| {
175+
if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
176+
})
177+
.filter_map(|t| {
178+
if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None }
179+
})
179180
.map(|t| format!(
180-
r#"<link rel="stylesheet" type="text/css" href="{}.css">"#,
181-
Escape(&format!("{}{}{}", static_root_path, t, page.resource_suffix))
181+
r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#,
182+
Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
183+
if t.1 { "disabled" } else { "" },
184+
if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
182185
))
183186
.collect::<String>(),
184187
suffix = page.resource_suffix,

src/librustdoc/html/render.rs

+65-29
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,8 @@ crate struct SharedContext {
188188
/// This flag indicates whether listings of modules (in the side bar and documentation itself)
189189
/// should be ordered alphabetically or in order of appearance (in the source code).
190190
pub sort_modules_alphabetically: bool,
191-
/// Additional themes to be added to the generated docs.
192-
pub themes: Vec<PathBuf>,
191+
/// Additional CSS files to be added to the generated docs.
192+
pub style_files: Vec<StylePath>,
193193
/// Suffix to be added on resource files (if suffix is "-v2" then "light.css" becomes
194194
/// "light-v2.css").
195195
pub resource_suffix: String,
@@ -418,6 +418,14 @@ impl Serialize for TypeWithKind {
418418
}
419419
}
420420

421+
#[derive(Debug, Clone)]
422+
pub struct StylePath {
423+
/// The path to the theme
424+
pub path: PathBuf,
425+
/// What the `disabled` attribute should be set to in the HTML tag
426+
pub disabled: bool,
427+
}
428+
421429
thread_local!(static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
422430
thread_local!(pub static CURRENT_DEPTH: Cell<usize> = Cell::new(0));
423431

@@ -461,7 +469,7 @@ pub fn run(
461469
id_map,
462470
playground_url,
463471
sort_modules_alphabetically,
464-
themes,
472+
themes: style_files,
465473
extension_css,
466474
extern_html_root_urls,
467475
resource_suffix,
@@ -531,7 +539,7 @@ pub fn run(
531539
layout,
532540
created_dirs: Default::default(),
533541
sort_modules_alphabetically,
534-
themes,
542+
style_files,
535543
resource_suffix,
536544
static_root_path,
537545
fs: DocFS::new(&errors),
@@ -540,6 +548,19 @@ pub fn run(
540548
playground,
541549
};
542550

551+
// Add the default themes to the `Vec` of stylepaths
552+
//
553+
// Note that these must be added before `sources::render` is called
554+
// so that the resulting source pages are styled
555+
//
556+
// `light.css` is not disabled because it is the stylesheet that stays loaded
557+
// by the browser as the theme stylesheet. The theme system (hackily) works by
558+
// changing the href to this stylesheet. All other themes are disabled to
559+
// prevent rule conflicts
560+
scx.style_files.push(StylePath { path: PathBuf::from("light.css"), disabled: false });
561+
scx.style_files.push(StylePath { path: PathBuf::from("dark.css"), disabled: true });
562+
scx.style_files.push(StylePath { path: PathBuf::from("ayu.css"), disabled: true });
563+
543564
let dst = output;
544565
scx.ensure_dir(&dst)?;
545566
krate = sources::render(&dst, &mut scx, krate)?;
@@ -616,11 +637,40 @@ fn write_shared(
616637
// then we'll run over the "official" styles.
617638
let mut themes: FxHashSet<String> = FxHashSet::default();
618639

619-
for entry in &cx.shared.themes {
620-
let content = try_err!(fs::read(&entry), &entry);
621-
let theme = try_none!(try_none!(entry.file_stem(), &entry).to_str(), &entry);
622-
let extension = try_none!(try_none!(entry.extension(), &entry).to_str(), &entry);
623-
cx.shared.fs.write(cx.path(&format!("{}.{}", theme, extension)), content.as_slice())?;
640+
for entry in &cx.shared.style_files {
641+
let theme = try_none!(try_none!(entry.path.file_stem(), &entry.path).to_str(), &entry.path);
642+
let extension =
643+
try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path);
644+
645+
// Handle the official themes
646+
match theme {
647+
"light" => write_minify(
648+
&cx.shared.fs,
649+
cx.path("light.css"),
650+
static_files::themes::LIGHT,
651+
options.enable_minification,
652+
)?,
653+
"dark" => write_minify(
654+
&cx.shared.fs,
655+
cx.path("dark.css"),
656+
static_files::themes::DARK,
657+
options.enable_minification,
658+
)?,
659+
"ayu" => write_minify(
660+
&cx.shared.fs,
661+
cx.path("ayu.css"),
662+
static_files::themes::AYU,
663+
options.enable_minification,
664+
)?,
665+
_ => {
666+
// Handle added third-party themes
667+
let content = try_err!(fs::read(&entry.path), &entry.path);
668+
cx.shared
669+
.fs
670+
.write(cx.path(&format!("{}.{}", theme, extension)), content.as_slice())?;
671+
}
672+
};
673+
624674
themes.insert(theme.to_owned());
625675
}
626676

@@ -634,20 +684,6 @@ fn write_shared(
634684
write(cx.path("brush.svg"), static_files::BRUSH_SVG)?;
635685
write(cx.path("wheel.svg"), static_files::WHEEL_SVG)?;
636686
write(cx.path("down-arrow.svg"), static_files::DOWN_ARROW_SVG)?;
637-
write_minify(
638-
&cx.shared.fs,
639-
cx.path("light.css"),
640-
static_files::themes::LIGHT,
641-
options.enable_minification,
642-
)?;
643-
themes.insert("light".to_owned());
644-
write_minify(
645-
&cx.shared.fs,
646-
cx.path("dark.css"),
647-
static_files::themes::DARK,
648-
options.enable_minification,
649-
)?;
650-
themes.insert("dark".to_owned());
651687

652688
let mut themes: Vec<&String> = themes.iter().collect();
653689
themes.sort();
@@ -958,7 +994,7 @@ themePicker.onblur = handleThemeButtonsBlur;
958994
})
959995
.collect::<String>()
960996
);
961-
let v = layout::render(&cx.shared.layout, &page, "", content, &cx.shared.themes);
997+
let v = layout::render(&cx.shared.layout, &page, "", content, &cx.shared.style_files);
962998
cx.shared.fs.write(&dst, v.as_bytes())?;
963999
}
9641000
}
@@ -1376,7 +1412,7 @@ impl Context {
13761412
&page,
13771413
sidebar,
13781414
|buf: &mut Buffer| all.print(buf),
1379-
&self.shared.themes,
1415+
&self.shared.style_files,
13801416
);
13811417
self.shared.fs.write(&final_file, v.as_bytes())?;
13821418

@@ -1385,9 +1421,9 @@ impl Context {
13851421
page.description = "Settings of Rustdoc";
13861422
page.root_path = "./";
13871423

1388-
let mut themes = self.shared.themes.clone();
1424+
let mut style_files = self.shared.style_files.clone();
13891425
let sidebar = "<p class='location'>Settings</p><div class='sidebar-elems'></div>";
1390-
themes.push(PathBuf::from("settings.css"));
1426+
style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false });
13911427
let v = layout::render(
13921428
&self.shared.layout,
13931429
&page,
@@ -1396,7 +1432,7 @@ impl Context {
13961432
self.shared.static_root_path.as_deref().unwrap_or("./"),
13971433
&self.shared.resource_suffix,
13981434
),
1399-
&themes,
1435+
&style_files,
14001436
);
14011437
self.shared.fs.write(&settings_file, v.as_bytes())?;
14021438

@@ -1458,7 +1494,7 @@ impl Context {
14581494
&page,
14591495
|buf: &mut _| print_sidebar(self, it, buf),
14601496
|buf: &mut _| print_item(self, it, buf),
1461-
&self.shared.themes,
1497+
&self.shared.style_files,
14621498
)
14631499
} else {
14641500
let mut url = self.root_path();

src/librustdoc/html/sources.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ impl<'a> SourceCollector<'a> {
123123
&page,
124124
"",
125125
|buf: &mut _| print_src(buf, &contents),
126-
&self.scx.themes,
126+
&self.scx.style_files,
127127
);
128128
self.scx.fs.write(&cur, v.as_bytes())?;
129129
self.scx.local_sources.insert(p, href);

0 commit comments

Comments
 (0)