about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Howell <michael@notriddle.com>2025-01-29 09:34:36 -0700
committerMichael Howell <michael@notriddle.com>2025-01-29 09:35:44 -0700
commit68646e9e5fd6731106c47696dbe04a6945996197 (patch)
tree860b0908eed9614d6e0bafa9ffb13586d0fc23f7
parentd94b64dcefcdf4ad29e8d5f8240389d9506968e5 (diff)
downloadrust-68646e9e5fd6731106c47696dbe04a6945996197.tar.gz
rust-68646e9e5fd6731106c47696dbe04a6945996197.zip
rustdoc: run css and html minifier at build instead of runtime
This way, adding a bunch of comments to the JS files won't make
rustdoc slower.
-rw-r--r--src/librustdoc/Cargo.toml1
-rw-r--r--src/librustdoc/build.rs24
-rw-r--r--src/librustdoc/config.rs4
-rw-r--r--src/librustdoc/html/render/write_shared.rs10
-rw-r--r--src/librustdoc/html/static_files.rs28
5 files changed, 35 insertions, 32 deletions
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 70749f7cb17..d9bd11267da 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -33,6 +33,7 @@ features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"]
 
 [build-dependencies]
 sha2 = "0.10.8"
+minifier = { version = "0.3.2", default-features = false }
 
 [dev-dependencies]
 expect-test = "1.4.0"
diff --git a/src/librustdoc/build.rs b/src/librustdoc/build.rs
index 69337fb1d25..119836257fd 100644
--- a/src/librustdoc/build.rs
+++ b/src/librustdoc/build.rs
@@ -1,3 +1,6 @@
+use std::str;
+
+use sha2::Digest;
 fn main() {
     // generate sha256 files
     // this avoids having to perform hashing at runtime
@@ -35,14 +38,27 @@ fn main() {
     for path in files {
         let inpath = format!("html/{path}");
         println!("cargo::rerun-if-changed={inpath}");
-        let bytes = std::fs::read(inpath).expect("static path exists");
-        use sha2::Digest;
-        let bytes = sha2::Sha256::digest(bytes);
-        let mut digest = format!("-{bytes:x}");
+        let data_bytes = std::fs::read(&inpath).expect("static path exists");
+        let hash_bytes = sha2::Sha256::digest(&data_bytes);
+        let mut digest = format!("-{hash_bytes:x}");
         digest.truncate(9);
         let outpath = std::path::PathBuf::from(format!("{out_dir}/{path}.sha256"));
         std::fs::create_dir_all(outpath.parent().expect("all file paths are in a directory"))
             .expect("should be able to write to out_dir");
         std::fs::write(&outpath, digest.as_bytes()).expect("write to out_dir");
+        let minified_path = std::path::PathBuf::from(format!("{out_dir}/{path}.min"));
+        if path.ends_with(".js") || path.ends_with(".css") {
+            let minified: String = if path.ends_with(".css") {
+                minifier::css::minify(str::from_utf8(&data_bytes).unwrap())
+                    .unwrap()
+                    .to_string()
+                    .into()
+            } else {
+                minifier::js::minify(str::from_utf8(&data_bytes).unwrap()).to_string().into()
+            };
+            std::fs::write(&minified_path, minified.as_bytes()).expect("write to out_dir");
+        } else {
+            std::fs::copy(&inpath, &minified_path).unwrap();
+        }
     }
 }
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 80bc6cebd2a..e9b0fdcc7d8 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -458,7 +458,7 @@ impl Options {
         let to_check = matches.opt_strs("check-theme");
         if !to_check.is_empty() {
             let mut content =
-                std::str::from_utf8(static_files::STATIC_FILES.rustdoc_css.bytes).unwrap();
+                std::str::from_utf8(static_files::STATIC_FILES.rustdoc_css.src_bytes).unwrap();
             if let Some((_, inside)) = content.split_once("/* Begin theme: light */") {
                 content = inside;
             }
@@ -607,7 +607,7 @@ impl Options {
         let mut themes = Vec::new();
         if matches.opt_present("theme") {
             let mut content =
-                std::str::from_utf8(static_files::STATIC_FILES.rustdoc_css.bytes).unwrap();
+                std::str::from_utf8(static_files::STATIC_FILES.rustdoc_css.src_bytes).unwrap();
             if let Some((_, inside)) = content.split_once("/* Begin theme: light */") {
                 content = inside;
             }
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index fb6f3bc2c76..57d07c05c11 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -207,14 +207,8 @@ fn write_static_files(
     if opt.emit.is_empty() || opt.emit.contains(&EmitType::Toolchain) {
         static_files::for_each(|f: &static_files::StaticFile| {
             let filename = static_dir.join(f.output_filename());
-            let contents: &[u8];
-            let contents_vec: Vec<u8>;
-            if opt.disable_minification {
-                contents = f.bytes;
-            } else {
-                contents_vec = f.minified();
-                contents = &contents_vec;
-            };
+            let contents: &[u8] =
+                if opt.disable_minification { f.src_bytes } else { f.minified_bytes };
             fs::write(&filename, contents).map_err(|e| PathError::new(e, &filename))
         })?;
     }
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index 6457ac731cb..b877a852640 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -8,26 +8,18 @@ use std::{fmt, str};
 
 pub(crate) struct StaticFile {
     pub(crate) filename: PathBuf,
-    pub(crate) bytes: &'static [u8],
+    pub(crate) src_bytes: &'static [u8],
+    pub(crate) minified_bytes: &'static [u8],
 }
 
 impl StaticFile {
-    fn new(filename: &str, bytes: &'static [u8], sha256: &'static str) -> StaticFile {
-        Self { filename: static_filename(filename, sha256), bytes }
-    }
-
-    pub(crate) fn minified(&self) -> Vec<u8> {
-        let extension = match self.filename.extension() {
-            Some(e) => e,
-            None => return self.bytes.to_owned(),
-        };
-        if extension == "css" {
-            minifier::css::minify(str::from_utf8(self.bytes).unwrap()).unwrap().to_string().into()
-        } else if extension == "js" {
-            minifier::js::minify(str::from_utf8(self.bytes).unwrap()).to_string().into()
-        } else {
-            self.bytes.to_owned()
-        }
+    fn new(
+        filename: &str,
+        src_bytes: &'static [u8],
+        minified_bytes: &'static [u8],
+        sha256: &'static str,
+    ) -> StaticFile {
+        Self { filename: static_filename(filename, sha256), src_bytes, minified_bytes }
     }
 
     pub(crate) fn output_filename(&self) -> &Path {
@@ -68,7 +60,7 @@ macro_rules! static_files {
 
         // sha256 files are generated in build.rs
         pub(crate) static STATIC_FILES: std::sync::LazyLock<StaticFiles> = std::sync::LazyLock::new(|| StaticFiles {
-            $($field: StaticFile::new($file_path, include_bytes!($file_path), include_str!(concat!(env!("OUT_DIR"), "/", $file_path, ".sha256"))),)+
+            $($field: StaticFile::new($file_path, include_bytes!($file_path), include_bytes!(concat!(env!("OUT_DIR"), "/", $file_path, ".min")), include_str!(concat!(env!("OUT_DIR"), "/", $file_path, ".sha256"))),)+
         });
 
         pub(crate) fn for_each<E>(f: impl Fn(&StaticFile) -> Result<(), E>) -> Result<(), E> {