about summary refs log tree commit diff
path: root/src/librustdoc/html
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-07-14 17:11:02 +0000
committerbors <bors@rust-lang.org>2020-07-14 17:11:02 +0000
commit2002ebacfbca288830a3c308ddc8189705c608fe (patch)
treed02268730c1ae866eb4a1ec31e144592b868be3d /src/librustdoc/html
parentc724b67e1b474262917a5154d74e7072267593fe (diff)
parent5414eae4521d0b6141b9db4c44be144757e5d5fb (diff)
downloadrust-2002ebacfbca288830a3c308ddc8189705c608fe.tar.gz
rust-2002ebacfbca288830a3c308ddc8189705c608fe.zip
Auto merge of #74330 - Manishearth:rollup-mrc09pb, r=Manishearth
Rollup of 15 pull requests

Successful merges:

 - #71237 (Add Ayu theme to rustdoc)
 - #73720 (Clean up E0704 error explanation)
 - #73866 (Obviate #[allow(improper_ctypes_definitions)])
 - #73965 (typeck: check for infer before type impls trait)
 - #73986 (add (unchecked) indexing methods to raw (and NonNull) slices)
 - #74173 (Detect tuple struct incorrectly used as struct pat)
 - #74220 (Refactor Windows `parse_prefix`)
 - #74227 (Remove an unwrap in layout computation)
 - #74239 (Update llvm-project to latest origin/rustc/10.0-2020-05-05 commit )
 - #74257 (don't mark linux kernel module targets as a unix environment)
 - #74270 (typeck: report placeholder type error w/out span)
 - #74296 (Clarify the description for rfind)
 - #74310 (Use `ArrayVec` in `SparseBitSet`.)
 - #74316 (Remove unnecessary type hints from Wake internals)
 - #74324 (Update Clippy)

Failed merges:

r? @ghost
Diffstat (limited to 'src/librustdoc/html')
-rw-r--r--src/librustdoc/html/layout.rs25
-rw-r--r--src/librustdoc/html/render.rs94
-rw-r--r--src/librustdoc/html/sources.rs2
-rw-r--r--src/librustdoc/html/static/themes/ayu.css561
-rw-r--r--src/librustdoc/html/static_files.rs3
5 files changed, 644 insertions, 41 deletions
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index ea65b390527..cc6b38ebcdb 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -3,7 +3,7 @@ use std::path::PathBuf;
 use crate::externalfiles::ExternalHtml;
 use crate::html::escape::Escape;
 use crate::html::format::{Buffer, Print};
-use crate::html::render::ensure_trailing_slash;
+use crate::html::render::{ensure_trailing_slash, StylePath};
 
 #[derive(Clone)]
 pub struct Layout {
@@ -36,7 +36,7 @@ pub fn render<T: Print, S: Print>(
     page: &Page<'_>,
     sidebar: S,
     t: T,
-    themes: &[PathBuf],
+    style_files: &[StylePath],
 ) -> String {
     let static_root_path = page.static_root_path.unwrap_or(page.root_path);
     format!(
@@ -52,10 +52,7 @@ pub fn render<T: Print, S: Print>(
     <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
     <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
           id=\"mainThemeStyle\">\
-    {themes}\
-    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}dark{suffix}.css\">\
-    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}light{suffix}.css\" \
-          id=\"themeStyle\">\
+    {style_files}\
     <script src=\"{static_root_path}storage{suffix}.js\"></script>\
     <noscript><link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\"></noscript>\
     {css_extension}\
@@ -172,13 +169,19 @@ pub fn render<T: Print, S: Print>(
         after_content = layout.external_html.after_content,
         sidebar = Buffer::html().to_display(sidebar),
         krate = layout.krate,
-        themes = themes
+        style_files = style_files
             .iter()
-            .filter_map(|t| t.file_stem())
-            .filter_map(|t| t.to_str())
+            .filter_map(|t| {
+                if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
+            })
+            .filter_map(|t| {
+                if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None }
+            })
             .map(|t| format!(
-                r#"<link rel="stylesheet" type="text/css" href="{}.css">"#,
-                Escape(&format!("{}{}{}", static_root_path, t, page.resource_suffix))
+                r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#,
+                Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
+                if t.1 { "disabled" } else { "" },
+                if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
             ))
             .collect::<String>(),
         suffix = page.resource_suffix,
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 301896fd2c1..8fa581180ef 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -188,8 +188,8 @@ crate 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>,
+    /// Additional CSS files to be added to the generated docs.
+    pub style_files: Vec<StylePath>,
     /// Suffix to be added on resource files (if suffix is "-v2" then "light.css" becomes
     /// "light-v2.css").
     pub resource_suffix: String,
@@ -418,6 +418,14 @@ impl Serialize for TypeWithKind {
     }
 }
 
+#[derive(Debug, Clone)]
+pub struct StylePath {
+    /// The path to the theme
+    pub path: PathBuf,
+    /// What the `disabled` attribute should be set to in the HTML tag
+    pub disabled: bool,
+}
+
 thread_local!(static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
 thread_local!(pub static CURRENT_DEPTH: Cell<usize> = Cell::new(0));
 
@@ -461,7 +469,7 @@ pub fn run(
         id_map,
         playground_url,
         sort_modules_alphabetically,
-        themes,
+        themes: style_files,
         extension_css,
         extern_html_root_urls,
         resource_suffix,
@@ -531,7 +539,7 @@ pub fn run(
         layout,
         created_dirs: Default::default(),
         sort_modules_alphabetically,
-        themes,
+        style_files,
         resource_suffix,
         static_root_path,
         fs: DocFS::new(&errors),
@@ -540,6 +548,19 @@ pub fn run(
         playground,
     };
 
+    // Add the default themes to the `Vec` of stylepaths
+    //
+    // Note that these must be added before `sources::render` is called
+    // so that the resulting source pages are styled
+    //
+    // `light.css` is not disabled because it is the stylesheet that stays loaded
+    // by the browser as the theme stylesheet. The theme system (hackily) works by
+    // changing the href to this stylesheet. All other themes are disabled to
+    // prevent rule conflicts
+    scx.style_files.push(StylePath { path: PathBuf::from("light.css"), disabled: false });
+    scx.style_files.push(StylePath { path: PathBuf::from("dark.css"), disabled: true });
+    scx.style_files.push(StylePath { path: PathBuf::from("ayu.css"), disabled: true });
+
     let dst = output;
     scx.ensure_dir(&dst)?;
     krate = sources::render(&dst, &mut scx, krate)?;
@@ -616,11 +637,40 @@ fn write_shared(
     // then we'll run over the "official" styles.
     let mut themes: FxHashSet<String> = FxHashSet::default();
 
-    for entry in &cx.shared.themes {
-        let content = try_err!(fs::read(&entry), &entry);
-        let theme = try_none!(try_none!(entry.file_stem(), &entry).to_str(), &entry);
-        let extension = try_none!(try_none!(entry.extension(), &entry).to_str(), &entry);
-        cx.shared.fs.write(cx.path(&format!("{}.{}", theme, extension)), content.as_slice())?;
+    for entry in &cx.shared.style_files {
+        let theme = try_none!(try_none!(entry.path.file_stem(), &entry.path).to_str(), &entry.path);
+        let extension =
+            try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path);
+
+        // Handle the official themes
+        match theme {
+            "light" => write_minify(
+                &cx.shared.fs,
+                cx.path("light.css"),
+                static_files::themes::LIGHT,
+                options.enable_minification,
+            )?,
+            "dark" => write_minify(
+                &cx.shared.fs,
+                cx.path("dark.css"),
+                static_files::themes::DARK,
+                options.enable_minification,
+            )?,
+            "ayu" => write_minify(
+                &cx.shared.fs,
+                cx.path("ayu.css"),
+                static_files::themes::AYU,
+                options.enable_minification,
+            )?,
+            _ => {
+                // Handle added third-party themes
+                let content = try_err!(fs::read(&entry.path), &entry.path);
+                cx.shared
+                    .fs
+                    .write(cx.path(&format!("{}.{}", theme, extension)), content.as_slice())?;
+            }
+        };
+
         themes.insert(theme.to_owned());
     }
 
@@ -634,20 +684,6 @@ fn write_shared(
     write(cx.path("brush.svg"), static_files::BRUSH_SVG)?;
     write(cx.path("wheel.svg"), static_files::WHEEL_SVG)?;
     write(cx.path("down-arrow.svg"), static_files::DOWN_ARROW_SVG)?;
-    write_minify(
-        &cx.shared.fs,
-        cx.path("light.css"),
-        static_files::themes::LIGHT,
-        options.enable_minification,
-    )?;
-    themes.insert("light".to_owned());
-    write_minify(
-        &cx.shared.fs,
-        cx.path("dark.css"),
-        static_files::themes::DARK,
-        options.enable_minification,
-    )?;
-    themes.insert("dark".to_owned());
 
     let mut themes: Vec<&String> = themes.iter().collect();
     themes.sort();
@@ -958,7 +994,7 @@ themePicker.onblur = handleThemeButtonsBlur;
                     })
                     .collect::<String>()
             );
-            let v = layout::render(&cx.shared.layout, &page, "", content, &cx.shared.themes);
+            let v = layout::render(&cx.shared.layout, &page, "", content, &cx.shared.style_files);
             cx.shared.fs.write(&dst, v.as_bytes())?;
         }
     }
@@ -1376,7 +1412,7 @@ impl Context {
             &page,
             sidebar,
             |buf: &mut Buffer| all.print(buf),
-            &self.shared.themes,
+            &self.shared.style_files,
         );
         self.shared.fs.write(&final_file, v.as_bytes())?;
 
@@ -1385,9 +1421,9 @@ impl Context {
         page.description = "Settings of Rustdoc";
         page.root_path = "./";
 
-        let mut themes = self.shared.themes.clone();
+        let mut style_files = self.shared.style_files.clone();
         let sidebar = "<p class='location'>Settings</p><div class='sidebar-elems'></div>";
-        themes.push(PathBuf::from("settings.css"));
+        style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false });
         let v = layout::render(
             &self.shared.layout,
             &page,
@@ -1396,7 +1432,7 @@ impl Context {
                 self.shared.static_root_path.as_deref().unwrap_or("./"),
                 &self.shared.resource_suffix,
             ),
-            &themes,
+            &style_files,
         );
         self.shared.fs.write(&settings_file, v.as_bytes())?;
 
@@ -1458,7 +1494,7 @@ impl Context {
                 &page,
                 |buf: &mut _| print_sidebar(self, it, buf),
                 |buf: &mut _| print_item(self, it, buf),
-                &self.shared.themes,
+                &self.shared.style_files,
             )
         } else {
             let mut url = self.root_path();
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index f0900c34a4b..03f79b93186 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -123,7 +123,7 @@ impl<'a> SourceCollector<'a> {
             &page,
             "",
             |buf: &mut _| print_src(buf, &contents),
-            &self.scx.themes,
+            &self.scx.style_files,
         );
         self.scx.fs.write(&cur, v.as_bytes())?;
         self.scx.local_sources.insert(p, href);
diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css
new file mode 100644
index 00000000000..bc21c28750f
--- /dev/null
+++ b/src/librustdoc/html/static/themes/ayu.css
@@ -0,0 +1,561 @@
+/*
+Based off of the Ayu theme
+Original by Dempfi (https://github.com/dempfi/ayu)
+*/
+
+/* General structure and fonts */
+
+body {
+	background-color: #0f1419;
+	color: #c5c5c5;
+}
+
+h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
+	color: white;
+}
+h1.fqn {
+	border-bottom-color: #5c6773;
+}
+h1.fqn  a {
+	color: #fff;
+}
+h2, h3:not(.impl):not(.method):not(.type):not(.tymethod) {
+	border-bottom-color: #5c6773;
+}
+h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) {
+	border: none;
+}
+
+.in-band {
+	background-color: #0f1419;
+}
+
+.invisible {
+	background: rgba(0, 0, 0, 0);
+}
+
+code {
+	color: #ffb454;
+}
+h3 > code, h4 > code, h5 > code {
+	color: #e6e1cf;
+}
+pre > code {
+    color: #e6e1cf; 
+}
+span code {
+    color: #e6e1cf;
+}
+.docblock a > code {
+    color: #39AFD7 !important;
+}
+.docblock code, .docblock-short code {
+	background-color: #191f26;
+}
+pre {
+	color: #e6e1cf;
+	background-color: #191f26;
+}
+
+.sidebar {
+	background-color: #14191f;
+}
+
+/* Improve the scrollbar display on firefox */
+* {
+	scrollbar-color: #5c6773 transparent;
+}
+
+.sidebar {
+	scrollbar-color: #5c6773 transparent;
+}
+
+/* Improve the scrollbar display on webkit-based browsers */
+::-webkit-scrollbar-track {
+	background-color: transparent;
+}
+::-webkit-scrollbar-thumb {
+	background-color: #5c6773;
+}
+.sidebar::-webkit-scrollbar-track {
+	background-color: transparent;
+}
+.sidebar::-webkit-scrollbar-thumb {
+	background-color: #5c6773;
+}
+
+.sidebar .current {
+	background-color: transparent;
+	color: #ffb44c;
+}
+
+.source .sidebar {
+	background-color: #0f1419;
+}
+
+.sidebar .location {
+	border-color: #000;
+	background-color: #0f1419;
+	color: #fff;
+}
+
+.sidebar-elems .location {
+    color: #ff7733;
+}
+
+.sidebar-elems .location a {
+    color: #fff;
+}
+
+.sidebar .version {
+	border-bottom-color: #DDD;
+}
+
+.sidebar-title {
+	border-top-color: #5c6773;
+	border-bottom-color: #5c6773;
+}
+
+.block a:hover {
+	background: transparent;
+	color: #ffb44c;
+}
+
+.line-numbers span { color: #5c6773ab; }
+.line-numbers .line-highlighted {
+    background-color: rgba(255, 236, 164, 0.06) !important;
+    padding-right: 4px;
+    border-right: 1px solid #ffb44c;
+}
+
+.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
+	border-bottom-color: #5c6773;
+}
+
+.docblock table, .docblock table td, .docblock table th {
+	border-color: #5c6773;
+}
+
+.content .method .where,
+.content .fn .where,
+.content .where.fmt-newline {
+	color: #c5c5c5;
+}
+
+.content .highlighted {
+	color: #000 !important;
+	background-color: #c6afb3;
+}
+.content .highlighted a, .content .highlighted span { color: #000 !important; }
+.content .highlighted {
+	background-color: #c6afb3;
+}
+.search-results a {
+	color: #0096cf;
+}
+.search-results a span.desc {
+	color: #c5c5c5;
+}
+
+.content .stability::before { color: #ccc; }
+
+.content span.foreigntype, .content a.foreigntype { color: #ef57ff; }
+.content span.union, .content a.union { color: #98a01c; }
+.content span.constant, .content a.constant,
+.content span.static, .content a.static { color: #6380a0; }
+.content span.primitive, .content a.primitive { color: #32889b; }
+.content span.traitalias, .content a.traitalias { color: #57d399; }
+.content span.keyword, .content a.keyword { color: #de5249; }
+
+.content span.externcrate, .content span.mod, .content a.mod {
+    color: #acccf9;
+}
+.content span.struct, .content a.struct {
+    color: #ffa0a5;
+}
+.content span.enum, .content a.enum {
+    color: #99e0c9;
+}
+.content span.trait, .content a.trait {
+    color: #39AFD7;
+}
+.content span.type, .content a.type {
+    color: #cfbcf5;
+}
+.content span.fn, .content a.fn, .content span.method,
+.content a.method, .content span.tymethod,
+.content a.tymethod, .content .fnname {
+    color: #fdd687;
+}
+.content span.attr, .content a.attr, .content span.derive,
+.content a.derive, .content span.macro, .content a.macro {
+    color: #a37acc;
+}
+
+pre.rust .comment, pre.rust .doccomment { 
+	color: #788797;
+	font-style: italic;
+}
+
+nav:not(.sidebar) {
+	border-bottom-color: #e0e0e0;
+}
+nav.main .current {
+	border-top-color: #5c6773;
+	border-bottom-color: #5c6773;
+}
+nav.main .separator {
+	border: 1px solid #5c6773;
+}
+a {
+	color: #c5c5c5;
+}
+
+.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
+.docblock-short a:not(.srclink):not(.test-arrow), .stability a {
+	color: #39AFD7;
+}
+
+.stab.internal a {
+	color: #304FFE;
+}
+
+.collapse-toggle {
+	color: #999;
+}
+
+#crate-search {
+	color: #c5c5c5;
+	background-color: #141920;
+	border-radius: 4px;
+	box-shadow: none;
+	border-color: #5c6773;
+}
+
+.search-input {
+    color: #ffffff;
+    background-color: #141920;
+    box-shadow: none;
+    transition: box-shadow 150ms ease-in-out;
+    border-radius: 4px;
+    margin-left: 8px;
+}
+
+#crate-search+.search-input:focus {
+    box-shadow: 0px 6px 20px 0px black;
+}
+
+.search-focus:disabled {
+	color: #929292;
+}
+
+.module-item .stab {
+	color: #000;
+}
+
+.stab.unstable,
+.stab.internal,
+.stab.deprecated,
+.stab.portability {
+    color: #c5c5c5;
+	background: #314559 !important;
+	border-style: none !important;
+	border-radius: 4px;
+	padding: 3px 6px 3px 6px;
+}
+
+.stab.portability > code {
+	color: #e6e1cf;
+	background-color: transparent;
+}
+
+#help > div {
+    background: #14191f;
+    box-shadow: 0px 6px 20px 0px black;
+    border: none;
+    border-radius: 4px;
+}
+
+.since {
+	color: grey;
+}
+
+tr.result span.primitive::after, tr.result span.keyword::after {
+	color: #788797;
+}
+
+.line-numbers :target { background-color: transparent; }
+
+/* Code highlighting */
+pre.rust .number, pre.rust .string { color: #b8cc52; }
+pre.rust .kw, pre.rust .kw-2, pre.rust .prelude-ty,
+pre.rust .bool-val, pre.rust .prelude-val,
+pre.rust .op, pre.rust .lifetime { color: #ff7733; }
+pre.rust .macro, pre.rust .macro-nonterminal { color: #a37acc; }
+pre.rust .question-mark {
+	color: #ff9011;
+}
+pre.rust .self {
+    color: #36a3d9;
+    font-style: italic;
+}
+pre.rust .attribute {
+    color: #e6e1cf;
+}
+pre.rust .attribute .ident, pre.rust .attribute .op {
+    color: #e6e1cf;
+}
+
+.example-wrap > pre.line-number {
+	color: #5c67736e;
+	border: none;
+}
+
+a.test-arrow {
+    font-size: 100%;
+    color: #788797;
+    border-radius: 4px;
+    background-color: rgba(255, 255, 255, 0);
+}
+
+a.test-arrow:hover {
+    background-color: rgba(242, 151, 24, 0.05);
+    color: #ffb44c;
+}
+
+.toggle-label {
+	color: #999;
+}
+
+:target > code, :target > .in-band {
+	background: rgba(255, 236, 164, 0.06);
+	border-right: 3px solid #ffb44c;
+}
+
+pre.compile_fail {
+	border-left: 2px solid rgba(255,0,0,.4);
+}
+
+pre.compile_fail:hover, .information:hover + pre.compile_fail {
+	border-left: 2px solid #f00;
+}
+
+pre.should_panic {
+	border-left: 2px solid rgba(255,0,0,.4);
+}
+
+pre.should_panic:hover, .information:hover + pre.should_panic {
+	border-left: 2px solid #f00;
+}
+
+pre.ignore {
+	border-left: 2px solid rgba(255,142,0,.6);
+}
+
+pre.ignore:hover, .information:hover + pre.ignore {
+	border-left: 2px solid #ff9200;
+}
+
+.tooltip.compile_fail {
+	color: rgba(255,0,0,.5);
+}
+
+.information > .compile_fail:hover {
+	color: #f00;
+}
+
+.tooltip.should_panic {
+	color: rgba(255,0,0,.5);
+}
+
+.information > .should_panic:hover {
+	color: #f00;
+}
+
+.tooltip.ignore {
+	color: rgba(255,142,0,.6);
+}
+
+.information > .ignore:hover {
+	color: #ff9200;
+}
+
+.search-failed a {
+	color: #39AFD7;
+}
+
+.tooltip .tooltiptext {
+    background-color: #314559;
+    color: #c5c5c5;
+    border: 1px solid #5c6773;
+}
+
+.tooltip .tooltiptext::after {
+	border-color: transparent #314559 transparent transparent;
+}
+
+#titles > div.selected {
+    background-color: #141920 !important;
+	border-bottom: 1px solid #ffb44c !important;
+	border-top: none;
+}
+
+#titles > div:not(.selected) {
+	background-color: transparent !important;
+	border: none;
+}
+
+#titles > div:hover {
+    border-bottom: 1px solid rgba(242, 151, 24, 0.3);
+}
+
+#titles > div > div.count {
+	color: #888;
+}
+
+/* rules that this theme does not need to set, here to satisfy the rule checker */
+/* note that a lot of these are partially set in some way (meaning they are set
+individually rather than as a group) */
+/* TODO: these rules should be at the bottom of the file but currently must be
+above the `@media (max-width: 700px)` rules due to a bug in the css checker */
+/* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */
+.content .highlighted.mod, .content .highlighted.externcrate {}
+.search-input:focus {}
+.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro {}
+.content .highlighted.trait {}
+.content span.struct,.content a.struct,.block a.current.struct {}
+#titles>div:hover,#titles>div.selected {}
+.content .highlighted.traitalias {}
+.content span.type,.content a.type,.block a.current.type {}
+.content span.union,.content a.union,.block a.current.union {}
+.content .highlighted.foreigntype {}
+pre.rust .lifetime {}
+.content .highlighted.primitive {}
+.content .highlighted.constant,.content .highlighted.static {}
+.stab.unstable {}
+.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod {}
+h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod) {}
+.content span.enum,.content a.enum,.block a.current.enum {}
+.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static {}
+.content span.keyword,.content a.keyword,.block a.current.keyword {}
+pre.rust .comment {}
+.content .highlighted.enum {}
+.content .highlighted.struct {}
+.content .highlighted.keyword {}
+.content span.traitalias,.content a.traitalias,.block a.current.traitalias {}
+.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname {}
+pre.rust .kw {}
+pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident {}
+.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype {}
+pre.rust .doccomment {}
+.stab.deprecated {}
+.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro {}
+.stab.portability {}
+.content .highlighted.union {}
+.content span.primitive,.content a.primitive,.block a.current.primitive {}
+.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod {}
+.content .highlighted.type {}
+pre.rust .kw-2,pre.rust .prelude-ty {}
+.content span.trait,.content a.trait,.block a.current.trait {}
+.stab.internal {}
+
+@media (max-width: 700px) {
+	.sidebar-menu {
+		background-color: #14191f;
+		border-bottom-color: #5c6773;
+		border-right-color: #5c6773;
+	}
+
+	.sidebar-elems {
+		background-color: #14191f;
+		border-right-color: #5c6773;
+	}
+
+	#sidebar-filler {
+		background-color: #14191f;
+		border-bottom-color: #5c6773;
+	}
+}
+
+kbd {
+	color: #c5c5c5;
+	background-color: #314559;
+	border-color: #5c6773;
+	border-bottom-color: #5c6773;
+	box-shadow-color: #c6cbd1;
+}
+
+#theme-picker, #settings-menu {
+	border-color: #5c6773;
+    background-color: #0f1419;
+}
+
+#theme-picker > img, #settings-menu > img {
+    filter: invert(100);
+}
+
+#theme-picker:hover, #theme-picker:focus,
+#settings-menu:hover, #settings-menu:focus {
+	border-color: #e0e0e0;
+}
+
+#theme-choices {
+	border-color: #5c6773;
+	background-color: #0f1419;
+}
+
+#theme-choices > button:not(:first-child) {
+	border-top-color: #c5c5c5;
+}
+
+#theme-choices > button:hover, #theme-choices > button:focus {
+	background-color: rgba(70, 70, 70, 0.33);
+}
+
+@media (max-width: 700px) {
+	#theme-picker {
+		background: #0f1419;
+	}
+}
+
+#all-types {
+	background-color: #14191f;
+}
+#all-types:hover {
+	background-color: rgba(70, 70, 70, 0.33);
+}
+
+.search-results td span.alias {
+	color: #c5c5c5;
+}
+.search-results td span.grey {
+	color: #999;
+}
+
+#sidebar-toggle {
+	background-color: #14191f;
+}
+#sidebar-toggle:hover {
+	background-color: rgba(70, 70, 70, 0.33);
+}
+#source-sidebar {
+	background-color: #14191f;
+}
+#source-sidebar > .title {
+	color: #fff;
+	border-bottom-color: #5c6773;
+}
+div.files > a:hover, div.name:hover {
+	background-color: #14191f;
+	color: #ffb44c;
+}
+div.files > .selected {
+	background-color: #14191f;
+	color: #ffb44c;
+}
+.setting-line > .title {
+	border-bottom-color: #5c6773;
+}
+input:checked + .slider {
+	background-color: #ffb454 !important;
+}
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index 6790f3bd5d0..6bd7e53cdfb 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -64,6 +64,9 @@ pub mod themes {
 
     /// The "dark" theme.
     pub static DARK: &str = include_str!("static/themes/dark.css");
+
+    /// The "ayu" theme.
+    pub static AYU: &str = include_str!("static/themes/ayu.css");
 }
 
 /// Files related to the Fira Sans font.