Skip to content

Commit d0ec58c

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 9d09331 + 8c45cf8 commit d0ec58c

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
@@ -187,8 +187,8 @@ crate struct SharedContext {
187187
/// This flag indicates whether listings of modules (in the side bar and documentation itself)
188188
/// should be ordered alphabetically or in order of appearance (in the source code).
189189
pub sort_modules_alphabetically: bool,
190-
/// Additional themes to be added to the generated docs.
191-
pub themes: Vec<PathBuf>,
190+
/// Additional CSS files to be added to the generated docs.
191+
pub style_files: Vec<StylePath>,
192192
/// Suffix to be added on resource files (if suffix is "-v2" then "light.css" becomes
193193
/// "light-v2.css").
194194
pub resource_suffix: String,
@@ -417,6 +417,14 @@ impl Serialize for TypeWithKind {
417417
}
418418
}
419419

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

@@ -460,7 +468,7 @@ pub fn run(
460468
id_map,
461469
playground_url,
462470
sort_modules_alphabetically,
463-
themes,
471+
themes: style_files,
464472
extension_css,
465473
extern_html_root_urls,
466474
resource_suffix,
@@ -530,7 +538,7 @@ pub fn run(
530538
layout,
531539
created_dirs: Default::default(),
532540
sort_modules_alphabetically,
533-
themes,
541+
style_files,
534542
resource_suffix,
535543
static_root_path,
536544
fs: DocFS::new(&errors),
@@ -539,6 +547,19 @@ pub fn run(
539547
playground,
540548
};
541549

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

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

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

651687
let mut themes: Vec<&String> = themes.iter().collect();
652688
themes.sort();
@@ -957,7 +993,7 @@ themePicker.onblur = handleThemeButtonsBlur;
957993
})
958994
.collect::<String>()
959995
);
960-
let v = layout::render(&cx.shared.layout, &page, "", content, &cx.shared.themes);
996+
let v = layout::render(&cx.shared.layout, &page, "", content, &cx.shared.style_files);
961997
cx.shared.fs.write(&dst, v.as_bytes())?;
962998
}
963999
}
@@ -1375,7 +1411,7 @@ impl Context {
13751411
&page,
13761412
sidebar,
13771413
|buf: &mut Buffer| all.print(buf),
1378-
&self.shared.themes,
1414+
&self.shared.style_files,
13791415
);
13801416
self.shared.fs.write(&final_file, v.as_bytes())?;
13811417

@@ -1384,9 +1420,9 @@ impl Context {
13841420
page.description = "Settings of Rustdoc";
13851421
page.root_path = "./";
13861422

1387-
let mut themes = self.shared.themes.clone();
1423+
let mut style_files = self.shared.style_files.clone();
13881424
let sidebar = "<p class='location'>Settings</p><div class='sidebar-elems'></div>";
1389-
themes.push(PathBuf::from("settings.css"));
1425+
style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false });
13901426
let v = layout::render(
13911427
&self.shared.layout,
13921428
&page,
@@ -1395,7 +1431,7 @@ impl Context {
13951431
self.shared.static_root_path.as_deref().unwrap_or("./"),
13961432
&self.shared.resource_suffix,
13971433
),
1398-
&themes,
1434+
&style_files,
13991435
);
14001436
self.shared.fs.write(&settings_file, v.as_bytes())?;
14011437

@@ -1457,7 +1493,7 @@ impl Context {
14571493
&page,
14581494
|buf: &mut _| print_sidebar(self, it, buf),
14591495
|buf: &mut _| print_item(self, it, buf),
1460-
&self.shared.themes,
1496+
&self.shared.style_files,
14611497
)
14621498
} else {
14631499
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)