From 26b773838fd13f93d4f559d5fb3671730675aa5a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Feb 2023 16:38:02 +0100 Subject: [PATCH] Automatically generate the correct static file names in rustdoc.css --- src/librustdoc/config.rs | 4 +- src/librustdoc/html/static/css/rustdoc.css | 26 +++----- src/librustdoc/html/static_files.rs | 70 +++++++++++++++++----- 3 files changed, 67 insertions(+), 33 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 2c514a0c8267b..4ce5add7131d1 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -417,7 +417,7 @@ impl Options { let to_check = matches.opt_strs("check-theme"); if !to_check.is_empty() { let paths = match theme::load_css_paths( - std::str::from_utf8(static_files::STATIC_FILES.theme_light_css.bytes).unwrap(), + std::str::from_utf8(&static_files::STATIC_FILES.theme_light_css.bytes).unwrap(), ) { Ok(p) => p, Err(e) => { @@ -560,7 +560,7 @@ impl Options { let mut themes = Vec::new(); if matches.opt_present("theme") { let paths = match theme::load_css_paths( - std::str::from_utf8(static_files::STATIC_FILES.theme_light_css.bytes).unwrap(), + std::str::from_utf8(&static_files::STATIC_FILES.theme_light_css.bytes).unwrap(), ) { Ok(p) => p, Err(e) => { diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index ee988090ca334..10f331f103662 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1,18 +1,10 @@ -/* When static files are updated, their suffixes need to be updated. - 1. In the top directory run: - ./x.py doc --stage 1 library/core - 2. Find the directory containing files named with updated suffixes: - find build -path '*'/stage1-std/'*'/static.files - 3. Copy the filenames with updated suffixes from the directory. -*/ - /* See FiraSans-LICENSE.txt for the Fira Sans license. */ @font-face { font-family: 'Fira Sans'; font-style: normal; font-weight: 400; src: local('Fira Sans'), - url("FiraSans-Regular-018c141bf0843ffd.woff2") format("woff2"); + url("/* REPLACE FiraSans-Regular.woff2 */") format("woff2"); font-display: swap; } @font-face { @@ -20,7 +12,7 @@ font-style: normal; font-weight: 500; src: local('Fira Sans Medium'), - url("FiraSans-Medium-8f9a781e4970d388.woff2") format("woff2"); + url("/* REPLACE FiraSans-Medium.woff2 */") format("woff2"); font-display: swap; } @@ -30,7 +22,7 @@ font-style: normal; font-weight: 400; src: local('Source Serif 4'), - url("SourceSerif4-Regular-46f98efaafac5295.ttf.woff2") format("woff2"); + url("/* REPLACE SourceSerif4-Regular.ttf.woff2 */") format("woff2"); font-display: swap; } @font-face { @@ -38,7 +30,7 @@ font-style: italic; font-weight: 400; src: local('Source Serif 4 Italic'), - url("SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2") format("woff2"); + url("/* REPLACE SourceSerif4-It.ttf.woff2 */") format("woff2"); font-display: swap; } @font-face { @@ -46,7 +38,7 @@ font-style: normal; font-weight: 700; src: local('Source Serif 4 Bold'), - url("SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2") format("woff2"); + url("/* REPLACE SourceSerif4-Bold.ttf.woff2 */") format("woff2"); font-display: swap; } @@ -57,28 +49,28 @@ font-weight: 400; /* Avoid using locally installed font because bad versions are in circulation: * see https://github.com/rust-lang/rust/issues/24355 */ - src: url("SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2") format("woff2"); + src: url("/* REPLACE SourceCodePro-Regular.ttf.woff2 */") format("woff2"); font-display: swap; } @font-face { font-family: 'Source Code Pro'; font-style: italic; font-weight: 400; - src: url("SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2") format("woff2"); + src: url("/* REPLACE SourceCodePro-It.ttf.woff2 */") format("woff2"); font-display: swap; } @font-face { font-family: 'Source Code Pro'; font-style: normal; font-weight: 600; - src: url("SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2") format("woff2"); + src: url("/* REPLACE SourceCodePro-Semibold.ttf.woff2 */") format("woff2"); font-display: swap; } /* Avoid using legacy CJK serif fonts in Windows like Batang. */ @font-face { font-family: 'NanumBarunGothic'; - src: url("NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2") format("woff2"); + src: url("/* REPLACE NanumBarunGothic.ttf.woff2 */") format("woff2"); font-display: swap; unicode-range: U+AC00-D7AF, U+1100-11FF, U+3130-318F, U+A960-A97F, U+D7B0-D7FF; } diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 767b974cc9109..400fedee33939 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -3,32 +3,49 @@ //! All the static files are included here for centralized access in case anything other than the //! HTML rendering code (say, the theme checker) needs to access one of these files. -use rustc_data_structures::fx::FxHasher; +use rustc_data_structures::fx::{FxHashMap, FxHasher}; +use std::borrow::Cow; use std::hash::Hasher; use std::path::{Path, PathBuf}; use std::{fmt, str}; pub(crate) struct StaticFile { pub(crate) filename: PathBuf, - pub(crate) bytes: &'static [u8], + pub(crate) bytes: Cow<'static, [u8]>, } impl StaticFile { - fn new(filename: &str, bytes: &'static [u8]) -> StaticFile { - Self { filename: static_filename(filename, bytes), bytes } + fn new( + filename: &str, + bytes: &'static [u8], + file_map: &mut FxHashMap, + ) -> StaticFile { + // For now, only `rustdoc.css` style file needs this mechanism but it can be extended + // pretty easily by changing this condition. + if filename.ends_with("/rustdoc.css") { + let bytes = replace_static_files_include(bytes, file_map); + Self { filename: static_filename(filename, &bytes), bytes: Cow::Owned(bytes) } + } else { + let ret = + Self { filename: static_filename(filename, bytes), bytes: Cow::Borrowed(bytes) }; + let filename = Path::new(filename).file_name().unwrap().to_str().unwrap().to_string(); + file_map + .insert(filename, ret.filename.file_name().unwrap().to_str().unwrap().to_string()); + ret + } } pub(crate) fn minified(&self) -> Vec { let extension = match self.filename.extension() { Some(e) => e, - None => return self.bytes.to_owned(), + None => return self.bytes.to_vec(), }; if extension == "css" { - minifier::css::minify(str::from_utf8(self.bytes).unwrap()).unwrap().to_string().into() + 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() + minifier::js::minify(str::from_utf8(&self.bytes).unwrap()).to_string().into() } else { - self.bytes.to_owned() + self.bytes.to_vec() } } @@ -45,6 +62,26 @@ impl fmt::Display for StaticFile { } } +/// This function goes through the CSS content and replaces all content wrapped between: +/// `/* REPLACE {content} */` (where `{content}` is what will be replaced.) +fn replace_static_files_include(bytes: &[u8], file_map: &FxHashMap) -> Vec { + let bytes = str::from_utf8(bytes).unwrap(); + let mut it = bytes.split("/* REPLACE "); + let mut content = String::with_capacity(bytes.len()); + while let Some(entry) = it.next() { + if content.is_empty() { + content.push_str(entry); + continue; + } + let mut parts = entry.splitn(2, " */"); + let file = parts.next().unwrap(); + let rest = parts.next().unwrap(); + content.push_str(file_map.get(file).unwrap()); + content.push_str(rest); + } + content.into() +} + /// Insert the provided suffix into a filename just before the extension. pub(crate) fn suffix_path(filename: &str, suffix: &str) -> PathBuf { // We use splitn vs Path::extension here because we might get a filename @@ -74,8 +111,11 @@ macro_rules! static_files { $(pub $field: StaticFile,)+ } - pub(crate) static STATIC_FILES: std::sync::LazyLock = std::sync::LazyLock::new(|| StaticFiles { - $($field: StaticFile::new($file_path, include_bytes!($file_path)),)+ + pub(crate) static STATIC_FILES: std::sync::LazyLock = std::sync::LazyLock::new(|| { + let mut map = FxHashMap::default(); + StaticFiles { + $($field: StaticFile::new($file_path, include_bytes!($file_path), &mut map),)+ + } }); pub(crate) fn for_each(f: impl Fn(&StaticFile) -> Result<(), E>) -> Result<(), E> { @@ -90,10 +130,6 @@ macro_rules! static_files { } static_files! { - rustdoc_css => "static/css/rustdoc.css", - settings_css => "static/css/settings.css", - noscript_css => "static/css/noscript.css", - normalize_css => "static/css/normalize.css", main_js => "static/js/main.js", search_js => "static/js/search.js", settings_js => "static/js/settings.js", @@ -125,6 +161,12 @@ static_files! { source_code_pro_license => "static/fonts/SourceCodePro-LICENSE.txt", nanum_barun_gothic_regular => "static/fonts/NanumBarunGothic.ttf.woff2", nanum_barun_gothic_license => "static/fonts/NanumBarunGothic-LICENSE.txt", + // It's important for the CSS files to be the last since we need to replace some of their + // content (the static file names). + rustdoc_css => "static/css/rustdoc.css", + settings_css => "static/css/settings.css", + noscript_css => "static/css/noscript.css", + normalize_css => "static/css/normalize.css", } pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/scrape-examples-help.md");