about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
authorMichael Howell <michael@notriddle.com>2023-09-13 15:08:45 -0700
committerMichael Howell <michael@notriddle.com>2023-09-15 07:40:17 -0700
commit7e86fd61e83717fc23b6141d2ba728aefbe5e168 (patch)
treef7000c35bcea979c3ad564f488dbdb6c97842486 /src/tools
parentcbccf800b85541187b3a8a17359c94c802e99748 (diff)
downloadrust-7e86fd61e83717fc23b6141d2ba728aefbe5e168.tar.gz
rust-7e86fd61e83717fc23b6141d2ba728aefbe5e168.zip
rustdoc: merge theme css into rustdoc.css
Based on
https://github.com/rust-lang/rust/pull/115812#issuecomment-1717960119

Having them in separate files used to make more sense, before the
migration to CSS variables made the theme files as small as they are
nowadays. This is already how docs.rs and mdBook do it.
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/rustdoc-themes/main.rs44
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs1
-rw-r--r--src/tools/tidy/src/rustdoc_css_themes.rs99
4 files changed, 129 insertions, 16 deletions
diff --git a/src/tools/rustdoc-themes/main.rs b/src/tools/rustdoc-themes/main.rs
index 7cac985a9a3..cc13df1f5ba 100644
--- a/src/tools/rustdoc-themes/main.rs
+++ b/src/tools/rustdoc-themes/main.rs
@@ -1,25 +1,37 @@
 use std::env::args;
-use std::fs::read_dir;
+use std::fs::File;
+use std::io::{BufRead, BufReader, BufWriter, Write};
 use std::path::Path;
 use std::process::{exit, Command};
 
-const FILES_TO_IGNORE: &[&str] = &["light.css"];
-
-fn get_folders<P: AsRef<Path>>(folder_path: P) -> Vec<String> {
+fn get_themes<P: AsRef<Path>>(style_path: P) -> Vec<String> {
     let mut ret = Vec::with_capacity(10);
 
-    for entry in read_dir(folder_path.as_ref()).expect("read_dir failed") {
-        let entry = entry.expect("Couldn't unwrap entry");
-        let path = entry.path();
+    const BEGIN_THEME_MARKER: &'static str = "/* Begin theme: ";
+    const END_THEME_MARKER: &'static str = "/* End theme: ";
+
+    let timestamp =
+        std::time::SystemTime::UNIX_EPOCH.elapsed().expect("time is after UNIX epoch").as_millis();
 
-        if !path.is_file() {
-            continue;
+    let mut in_theme = None;
+    for line in BufReader::new(File::open(style_path).expect("read rustdoc.css failed")).lines() {
+        let line = line.expect("read line from rustdoc.css failed");
+        let line = line.trim();
+        if line.starts_with(BEGIN_THEME_MARKER) {
+            let theme_name = &line[BEGIN_THEME_MARKER.len()..].trim().trim_end_matches("*/").trim();
+            let filename = format!("build/tmp/rustdoc.bootstrap.{timestamp}.{theme_name}.css");
+            in_theme = Some(BufWriter::new(
+                File::create(&filename).expect("failed to create temporary test css file"),
+            ));
+            ret.push(filename);
+        }
+        if let Some(in_theme) = in_theme.as_mut() {
+            in_theme.write_all(line.as_bytes()).expect("write to temporary test css file");
+            in_theme.write_all(b"\n").expect("write to temporary test css file");
         }
-        let filename = path.file_name().expect("file_name failed");
-        if FILES_TO_IGNORE.iter().any(|x| x == &filename) {
-            continue;
+        if line.starts_with(END_THEME_MARKER) {
+            in_theme = None;
         }
-        ret.push(format!("{}", path.display()));
     }
     ret
 }
@@ -32,10 +44,10 @@ fn main() {
         exit(1);
     }
     let rustdoc_bin = &argv[1];
-    let themes_folder = &argv[2];
-    let themes = get_folders(&themes_folder);
+    let style_path = &argv[2];
+    let themes = get_themes(&style_path);
     if themes.is_empty() {
-        eprintln!("No theme found in \"{}\"...", themes_folder);
+        eprintln!("No themes found in \"{}\"...", style_path);
         exit(1);
     }
     let arg_name = "--check-theme".to_owned();
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 9b19b8eecc7..ca160017202 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -64,6 +64,7 @@ pub mod fluent_alphabetical;
 pub mod mir_opt_tests;
 pub mod pal;
 pub mod primitive_docs;
+pub mod rustdoc_css_themes;
 pub mod rustdoc_gui_tests;
 pub mod style;
 pub mod target_specific_tests;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 5fa91715a07..5585e125f2d 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -104,6 +104,7 @@ fn main() {
         check!(ui_tests, &tests_path);
         check!(mir_opt_tests, &tests_path, bless);
         check!(rustdoc_gui_tests, &tests_path);
+        check!(rustdoc_css_themes, &librustdoc_path);
 
         // Checks that only make sense for the compiler.
         check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose);
diff --git a/src/tools/tidy/src/rustdoc_css_themes.rs b/src/tools/tidy/src/rustdoc_css_themes.rs
new file mode 100644
index 00000000000..852d6e14e91
--- /dev/null
+++ b/src/tools/tidy/src/rustdoc_css_themes.rs
@@ -0,0 +1,99 @@
+//! Tidy check to make sure light and dark themes are synchronized between
+//! JS-controlled rustdoc.css and noscript.css
+
+use std::path::Path;
+
+pub fn check(librustdoc_path: &Path, bad: &mut bool) {
+    let rustdoc_css = "html/static/css/rustdoc.css";
+    let noscript_css = "html/static/css/noscript.css";
+    let rustdoc_css_contents = std::fs::read_to_string(librustdoc_path.join(rustdoc_css))
+        .unwrap_or_else(|e| panic!("failed to read librustdoc/{rustdoc_css}: {e}"));
+    let noscript_css_contents = std::fs::read_to_string(librustdoc_path.join(noscript_css))
+        .unwrap_or_else(|e| panic!("failed to read librustdoc/{noscript_css}: {e}"));
+    compare_themes_from_files(
+        "light",
+        rustdoc_css_contents.lines().enumerate().map(|(i, l)| (i + 1, l.trim())),
+        noscript_css_contents.lines().enumerate().map(|(i, l)| (i + 1, l.trim())),
+        bad,
+    );
+    compare_themes_from_files(
+        "dark",
+        rustdoc_css_contents.lines().enumerate(),
+        noscript_css_contents.lines().enumerate(),
+        bad,
+    );
+}
+
+fn compare_themes_from_files<'a>(
+    name: &str,
+    mut rustdoc_css_lines: impl Iterator<Item = (usize, &'a str)>,
+    mut noscript_css_lines: impl Iterator<Item = (usize, &'a str)>,
+    bad: &mut bool,
+) {
+    let begin_theme_pat = format!("/* Begin theme: {name}");
+    let mut found_theme = None;
+    let mut found_theme_noscript = None;
+    while let Some((rustdoc_css_line_number, rustdoc_css_line)) = rustdoc_css_lines.next() {
+        if !rustdoc_css_line.starts_with(&begin_theme_pat) {
+            continue;
+        }
+        if let Some(found_theme) = found_theme {
+            tidy_error!(
+                bad,
+                "rustdoc.css contains two {name} themes on lines {rustdoc_css_line_number} and {found_theme}",
+            );
+            return;
+        }
+        found_theme = Some(rustdoc_css_line_number);
+        while let Some((noscript_css_line_number, noscript_css_line)) = noscript_css_lines.next() {
+            if !noscript_css_line.starts_with(&begin_theme_pat) {
+                continue;
+            }
+            if let Some(found_theme_noscript) = found_theme_noscript {
+                tidy_error!(
+                    bad,
+                    "noscript.css contains two {name} themes on lines {noscript_css_line_number} and {found_theme_noscript}",
+                );
+                return;
+            }
+            found_theme_noscript = Some(noscript_css_line_number);
+            compare_themes(name, &mut rustdoc_css_lines, &mut noscript_css_lines, bad);
+        }
+    }
+}
+
+fn compare_themes<'a>(
+    name: &str,
+    rustdoc_css_lines: impl Iterator<Item = (usize, &'a str)>,
+    noscript_css_lines: impl Iterator<Item = (usize, &'a str)>,
+    bad: &mut bool,
+) {
+    let end_theme_pat = format!("/* End theme: {name}");
+    for (
+        (rustdoc_css_line_number, rustdoc_css_line),
+        (noscript_css_line_number, noscript_css_line),
+    ) in rustdoc_css_lines.zip(noscript_css_lines)
+    {
+        if noscript_css_line.starts_with(":root {")
+            && rustdoc_css_line.starts_with(&format!(r#":root[data-theme="{name}"] {{"#))
+        {
+            // selectors are different between rustdoc.css and noscript.css
+            // that's why they both exist: one uses JS, the other uses media queries
+            continue;
+        }
+        if noscript_css_line.starts_with(&end_theme_pat)
+            && rustdoc_css_line.starts_with(&end_theme_pat)
+        {
+            break;
+        }
+        if rustdoc_css_line != noscript_css_line {
+            tidy_error!(
+                bad,
+                "noscript.css:{noscript_css_line_number} and rustdoc.css:{rustdoc_css_line_number} contain copies of {name} theme that are not the same",
+            );
+            eprintln!("- {noscript_css_line}");
+            eprintln!("+ {rustdoc_css_line}");
+            return;
+        }
+    }
+}