From 17de2309726801404cdc8a6ef3143456eeeecf9c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 13 Dec 2021 22:32:04 +0100 Subject: [PATCH] Fix new sidebar changes --- build.rs | 1 + src/utils/mod.rs | 2 +- src/utils/rustc_version.rs | 47 +++++++++ src/web/builds.rs | 32 +++---- src/web/crate_details.rs | 3 + src/web/mod.rs | 13 ++- src/web/source.rs | 5 +- src/web/statics.rs | 8 +- templates/rustdoc/head.html | 2 +- templates/style/rustdoc-2021-12-06.scss | 41 ++++++++ templates/style/rustdoc-common.scss | 121 ++++++++++++++++++++++++ templates/style/rustdoc.scss | 109 +-------------------- 12 files changed, 255 insertions(+), 129 deletions(-) create mode 100644 templates/style/rustdoc-2021-12-06.scss create mode 100644 templates/style/rustdoc-common.scss diff --git a/build.rs b/build.rs index 60c92cf05..7d440aeae 100644 --- a/build.rs +++ b/build.rs @@ -77,6 +77,7 @@ fn compile_sass() -> Result<(), Box> { // Compile rustdoc.scss -> rustdoc.css compile_sass_file("rustdoc", "rustdoc", &[])?; + compile_sass_file("rustdoc-2021-12-06", "rustdoc-2021-12-06", &[])?; // Compile vendored.scss -> vendored.css compile_sass_file( diff --git a/src/utils/mod.rs b/src/utils/mod.rs index d3b523983..9522ed720 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -6,7 +6,7 @@ pub use self::daemon::start_daemon; pub(crate) use self::html::rewrite_lol; pub use self::queue::{get_crate_priority, remove_crate_priority, set_crate_priority}; pub use self::queue_builder::queue_builder; -pub(crate) use self::rustc_version::parse_rustc_version; +pub(crate) use self::rustc_version::{get_correct_docsrs_style_file, parse_rustc_version}; #[cfg(test)] pub(crate) use self::cargo_metadata::{Dependency, Target}; diff --git a/src/utils/rustc_version.rs b/src/utils/rustc_version.rs index e5fb821e0..cbf46e4bc 100644 --- a/src/utils/rustc_version.rs +++ b/src/utils/rustc_version.rs @@ -1,5 +1,7 @@ use crate::error::Result; use anyhow::{anyhow, Context}; +use chrono::prelude::*; +use once_cell::sync::Lazy; use regex::Regex; /// Parses rustc commit hash from rustc version string @@ -19,6 +21,38 @@ pub fn parse_rustc_version>(version: S) -> Result { )) } +fn parse_rustc_date>(version: S) -> Result> { + static RE: Lazy = Lazy::new(|| Regex::new(r" (\d+)-(\d+)-(\d+)\)$").unwrap()); + + let cap = RE + .captures(version.as_ref()) + .with_context(|| anyhow!("Failed to parse rustc date"))?; + + let year = cap.get(1).unwrap().as_str(); + let month = cap.get(2).unwrap().as_str(); + let day = cap.get(3).unwrap().as_str(); + + Ok(Utc.ymd( + year.parse::().unwrap(), + month.parse::().unwrap(), + day.parse::().unwrap(), + )) +} + +/// Picks the correct "rustdoc.css" static file depending on which rustdoc version was used to +/// generate this version of this crate. +pub fn get_correct_docsrs_style_file(version: &str) -> Result { + let date = parse_rustc_date(version)?; + // This is the date where https://github.com/rust-lang/rust/pull/91356 was merged. + if Utc.ymd(2021, 12, 6) < date { + // If this is the new rustdoc layout, we need the newer docs.rs CSS file. + Ok("rustdoc-2021-12-06.css".to_owned()) + } else { + // By default, we return the old docs.rs CSS file. + Ok("rustdoc.css".to_owned()) + } +} + #[test] fn test_parse_rustc_version() { assert_eq!( @@ -30,3 +64,16 @@ fn test_parse_rustc_version() { "20160526-0.2.0-ba9ae23" ); } + +#[test] +fn test_get_correct_docsrs_style_file() { + assert_eq!( + get_correct_docsrs_style_file("rustc 1.10.0-nightly (57ef01513 2016-05-23)").unwrap(), + "rustdoc.css" + ); + assert_eq!( + get_correct_docsrs_style_file("docsrs 0.2.0 (ba9ae23 2022-05-26)").unwrap(), + "rustdoc-2021-12-06.css" + ); + assert!(get_correct_docsrs_style_file("docsrs 0.2.0").is_err(),); +} diff --git a/src/web/builds.rs b/src/web/builds.rs index a11b73735..d7f7e74cb 100644 --- a/src/web/builds.rs +++ b/src/web/builds.rs @@ -144,14 +144,14 @@ mod tests { .version("0.1.0") .builds(vec![ FakeBuild::default() - .rustc_version("rustc 1.0.0") + .rustc_version("rustc (blabla 2019-01-01)") .docsrs_version("docs.rs 1.0.0"), FakeBuild::default() .successful(false) - .rustc_version("rustc 2.0.0") + .rustc_version("rustc (blabla 2020-01-01)") .docsrs_version("docs.rs 2.0.0"), FakeBuild::default() - .rustc_version("rustc 3.0.0") + .rustc_version("rustc (blabla 2021-01-01)") .docsrs_version("docs.rs 3.0.0"), ]) .create()?; @@ -169,11 +169,11 @@ mod tests { .map(|row| row.text_contents()) .collect(); - assert!(rows[0].contains("rustc 3.0.0")); + assert!(rows[0].contains("rustc (blabla 2021-01-01)")); assert!(rows[0].contains("docs.rs 3.0.0")); - assert!(rows[1].contains("rustc 2.0.0")); + assert!(rows[1].contains("rustc (blabla 2020-01-01)")); assert!(rows[1].contains("docs.rs 2.0.0")); - assert!(rows[2].contains("rustc 1.0.0")); + assert!(rows[2].contains("rustc (blabla 2019-01-01)")); assert!(rows[2].contains("docs.rs 1.0.0")); Ok(()) @@ -188,14 +188,14 @@ mod tests { .version("0.1.0") .builds(vec![ FakeBuild::default() - .rustc_version("rustc 1.0.0") + .rustc_version("rustc (blabla 2019-01-01)") .docsrs_version("docs.rs 1.0.0"), FakeBuild::default() .successful(false) - .rustc_version("rustc 2.0.0") + .rustc_version("rustc (blabla 2020-01-01)") .docsrs_version("docs.rs 2.0.0"), FakeBuild::default() - .rustc_version("rustc 3.0.0") + .rustc_version("rustc (blabla 2021-01-01)") .docsrs_version("docs.rs 3.0.0"), ]) .create()?; @@ -214,7 +214,7 @@ mod tests { ); assert_eq!( value.pointer("/0/rustc_version"), - Some(&"rustc 3.0.0".into()) + Some(&"rustc (blabla 2021-01-01)".into()) ); assert!(value.pointer("/0/id").unwrap().is_i64()); assert!(serde_json::from_value::>( @@ -229,7 +229,7 @@ mod tests { ); assert_eq!( value.pointer("/1/rustc_version"), - Some(&"rustc 2.0.0".into()) + Some(&"rustc (blabla 2020-01-01)".into()) ); assert!(value.pointer("/1/id").unwrap().is_i64()); assert!(serde_json::from_value::>( @@ -244,7 +244,7 @@ mod tests { ); assert_eq!( value.pointer("/2/rustc_version"), - Some(&"rustc 1.0.0".into()) + Some(&"rustc (blabla 2019-01-01)".into()) ); assert!(value.pointer("/2/id").unwrap().is_i64()); assert!(serde_json::from_value::>( @@ -317,7 +317,7 @@ mod tests { .name("aquarelle") .version("0.1.0") .builds(vec![FakeBuild::default() - .rustc_version("rustc 1.0.0") + .rustc_version("rustc (blabla 2019-01-01)") .docsrs_version("docs.rs 1.0.0")]) .create()?; @@ -325,7 +325,7 @@ mod tests { .name("aquarelle") .version("0.2.0") .builds(vec![FakeBuild::default() - .rustc_version("rustc 1.0.0") + .rustc_version("rustc (blabla 2019-01-01)") .docsrs_version("docs.rs 1.0.0")]) .create()?; @@ -363,7 +363,7 @@ mod tests { .name("foo") .version("0.1.0") .builds(vec![FakeBuild::default() - .rustc_version("rustc 1.0.0") + .rustc_version("rustc (blabla 2019-01-01)") .docsrs_version("docs.rs 1.0.0")]) .create()?; @@ -382,7 +382,7 @@ mod tests { .name("foo") .version("0.1.0") .builds(vec![FakeBuild::default() - .rustc_version("rustc 1.0.0") + .rustc_version("rustc (blabla 2019-01-01)") .docsrs_version("docs.rs 1.0.0")]) .create()?; diff --git a/src/web/crate_details.rs b/src/web/crate_details.rs index a13ab2d5e..fd425c1e9 100644 --- a/src/web/crate_details.rs +++ b/src/web/crate_details.rs @@ -1,4 +1,5 @@ use super::{match_version, redirect_base, render_markdown, MatchSemver, MetaData}; +use crate::utils::get_correct_docsrs_style_file; use crate::{db::Pool, impl_webpage, repositories::RepositoryStatsUpdater, web::page::WebPage}; use chrono::{DateTime, Utc}; use iron::prelude::*; @@ -114,6 +115,7 @@ impl CrateDetails { releases.license, releases.documentation_url, releases.default_target, + releases.doc_rustc_version, doc_coverage.total_items, doc_coverage.documented_items, doc_coverage.total_items_needing_examples, @@ -159,6 +161,7 @@ impl CrateDetails { default_target: krate.get("default_target"), doc_targets: MetaData::parse_doc_targets(krate.get("doc_targets")), yanked: krate.get("yanked"), + rustdoc_css_file: get_correct_docsrs_style_file(krate.get("doc_rustc_version"))?, }; let documented_items: Option = krate.get("documented_items"); diff --git a/src/web/mod.rs b/src/web/mod.rs index 6125b7bce..28c47879b 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -2,6 +2,7 @@ pub(crate) mod page; +use crate::utils::get_correct_docsrs_style_file; use crate::utils::report_error; use anyhow::{anyhow, Context as _}; use log::info; @@ -534,6 +535,9 @@ pub(crate) struct MetaData { pub(crate) default_target: String, pub(crate) doc_targets: Vec, pub(crate) yanked: bool, + /// CSS file to use depending on the rustdoc version used to generate this version of this + /// crate. + pub(crate) rustdoc_css_file: String, } impl MetaData { @@ -552,7 +556,8 @@ impl MetaData { releases.rustdoc_status, releases.default_target, releases.doc_targets, - releases.yanked + releases.yanked, + releases.doc_rustc_version FROM releases INNER JOIN crates ON crates.id = releases.crate_id WHERE crates.name = $1 AND releases.version = $2", @@ -572,6 +577,7 @@ impl MetaData { default_target: row.get(5), doc_targets: MetaData::parse_doc_targets(row.get(6)), yanked: row.get(7), + rustdoc_css_file: get_correct_docsrs_style_file(row.get(8)).unwrap(), }) } @@ -927,6 +933,7 @@ mod test { "arm64-unknown-linux-gnu".to_string(), ], yanked: false, + rustdoc_css_file: "rustdoc.css".to_string(), }; let correct_json = json!({ @@ -942,6 +949,7 @@ mod test { "arm64-unknown-linux-gnu", ], "yanked": false, + "rustdoc_css_file": "rustdoc.css", }); assert_eq!(correct_json, serde_json::to_value(&metadata).unwrap()); @@ -960,6 +968,7 @@ mod test { "arm64-unknown-linux-gnu", ], "yanked": false, + "rustdoc_css_file": "rustdoc.css", }); assert_eq!(correct_json, serde_json::to_value(&metadata).unwrap()); @@ -978,6 +987,7 @@ mod test { "arm64-unknown-linux-gnu", ], "yanked": false, + "rustdoc_css_file": "rustdoc.css", }); assert_eq!(correct_json, serde_json::to_value(&metadata).unwrap()); @@ -1001,6 +1011,7 @@ mod test { default_target: "x86_64-unknown-linux-gnu".to_string(), doc_targets: vec![], yanked: false, + rustdoc_css_file: "rustdoc.css".to_string(), }, ); Ok(()) diff --git a/src/web/source.rs b/src/web/source.rs index 842755a7e..c238691c5 100644 --- a/src/web/source.rs +++ b/src/web/source.rs @@ -3,6 +3,7 @@ use crate::{ db::Pool, impl_webpage, + utils::get_correct_docsrs_style_file, web::{ error::Nope, file::File as DbFile, match_version, page::WebPage, redirect_base, MatchSemver, MetaData, Url, @@ -67,7 +68,8 @@ impl FileList { releases.files, releases.default_target, releases.doc_targets, - releases.yanked + releases.yanked, + releases.doc_rustc_version FROM releases LEFT OUTER JOIN crates ON crates.id = releases.crate_id WHERE crates.name = $1 AND releases.version = $2", @@ -147,6 +149,7 @@ impl FileList { default_target: rows[0].get(6), doc_targets: MetaData::parse_doc_targets(rows[0].get(7)), yanked: rows[0].get(8), + rustdoc_css_file: get_correct_docsrs_style_file(rows[0].get(9)).unwrap(), }, files: file_list, }) diff --git a/src/web/statics.rs b/src/web/statics.rs index babdc866f..5d154d8d3 100644 --- a/src/web/statics.rs +++ b/src/web/statics.rs @@ -1,7 +1,7 @@ use super::{error::Nope, redirect, redirect_base, STATIC_FILE_CACHE_DURATION}; use crate::utils::report_error; use anyhow::Context; -use chrono::Utc; +use chrono::prelude::*; use iron::{ headers::CacheDirective, headers::{CacheControl, ContentLength, ContentType, LastModified}, @@ -14,6 +14,8 @@ use std::{ffi::OsStr, fs, path::Path}; const VENDORED_CSS: &str = include_str!(concat!(env!("OUT_DIR"), "/vendored.css")); const STYLE_CSS: &str = include_str!(concat!(env!("OUT_DIR"), "/style.css")); const RUSTDOC_CSS: &str = include_str!(concat!(env!("OUT_DIR"), "/rustdoc.css")); +const RUSTDOC_2021_12_06_CSS: &str = + include_str!(concat!(env!("OUT_DIR"), "/rustdoc-2021-12-06.css")); const STATIC_SEARCH_PATHS: &[&str] = &["static", "vendor"]; pub(crate) fn static_handler(req: &mut Request) -> IronResult { @@ -25,6 +27,10 @@ pub(crate) fn static_handler(req: &mut Request) -> IronResult { "vendored.css" => serve_resource(VENDORED_CSS, ContentType("text/css".parse().unwrap())), "style.css" => serve_resource(STYLE_CSS, ContentType("text/css".parse().unwrap())), "rustdoc.css" => serve_resource(RUSTDOC_CSS, ContentType("text/css".parse().unwrap())), + "rustdoc-2021-12-06.css" => serve_resource( + RUSTDOC_2021_12_06_CSS, + ContentType("text/css".parse().unwrap()), + ), file => serve_file(file)?, }) } diff --git a/templates/rustdoc/head.html b/templates/rustdoc/head.html index 78791e9ce..f8f8cb611 100644 --- a/templates/rustdoc/head.html +++ b/templates/rustdoc/head.html @@ -1,5 +1,5 @@ {%- import "macros.html" as macros -%} - + diff --git a/templates/style/rustdoc-2021-12-06.scss b/templates/style/rustdoc-2021-12-06.scss new file mode 100644 index 000000000..d4e5610c4 --- /dev/null +++ b/templates/style/rustdoc-2021-12-06.scss @@ -0,0 +1,41 @@ +// FIXME: Use modules +@import "rustdoc-common"; + +// This file is needed to overload the previous docs.rs style. It is added into crates generated +// using rustdoc after https://github.com/rust-lang/rust/pull/91356 has been merged. + +#rustdoc_body_wrapper { + padding: 0; + + .sidebar { + margin-top: 0; + top: $top-navbar-height; + + .sidebar-menu { + top: $top-navbar-height; + } + } + + main { + padding-bottom: 50px; + } +} + +div.container-rustdoc { + > .docs-rs-footer { + bottom: 0; + right: 0; + } +} + +div.container-rustdoc:not(.source) { + > .docs-rs-footer { + left: 200px; + } +} + +div.rustdoc { + #sidebar-toggle { + top: 0; + } +} diff --git a/templates/style/rustdoc-common.scss b/templates/style/rustdoc-common.scss new file mode 100644 index 000000000..726699761 --- /dev/null +++ b/templates/style/rustdoc-common.scss @@ -0,0 +1,121 @@ +// FIXME: Use modules +@import "vars", "navbar", "themes", "fa", "footer"; + +// This rule is needed to be sure that the footer will always be at the bottom of the page. +#rustdoc_body_wrapper { + min-height: calc(100vh - #{$top-navbar-height + $footer-height + 2}); +} + +#clipboard { + cursor: pointer; +} + +// Force the navbar to be left-aligned on rustdoc pages +body.rustdoc-page > .nav-container > .container { + margin-left: 0; +} + +div.container-rustdoc { + text-align: left; + + > .docs-rs-footer { + width: unset; + } +} + +div.container-rustdoc { + width: unset; +} + +div.container-rustdoc:not(.source) { + // This is when the rustdoc sidebar "disappears" (for mobile mode). + @media (max-width: 700px) { + > .docs-rs-footer:not(.source) { + left: -15px; + } + } +} + +div.container-rustdoc.source { + > .docs-rs-footer { + left: -15px; + // This is needed because even though the sidebar only contains the header, it still takes + // all the height, going over the footer. + z-index: 1; + } +} + +// this is a super nasty override for help dialog in rustdocs +// see #52 for details +body.blur { + > :not(#help) { + filter: none; + -webkit-filter: none; + } + + > div.nav-container > *, + > div.docsrs-package-container > *, + > div.rustdoc > :not(#help) { + filter: blur(8px); + -webkit-filter: blur(8px); + opacity: 0.7; + } +} + +// rustdoc overrides +div.rustdoc { + $padding-x: 15px; + padding: 10px $padding-x 20px; + position: relative; + + @media (max-width: 700px) { + padding-top: 0; + } + + .sidebar { + @media (min-width: 701px) { + margin-top: $top-navbar-height; + } + + .block > ul > li { + margin-right: -10px; + } + + @media (max-width: 700px) { + margin-left: -2 * $padding-x; // offset the additional padding added by the parent containers + width: calc(100% + #{4 * $padding-x}); + + &.mobile { + top: $top-navbar-height; + margin-left: 0; // since the sidebar is now fixed position, remove the padding workaround + width: 100%; + + .sidebar-elems.show-it { + top: 45px + $top-navbar-height; + } + + #sidebar-filler { + top: $top-navbar-height; + } + } + } + } + + #source-sidebar { + top: $top-navbar-height; + } + + &:focus { + outline: unset; + } + + // Overriding some outdated rustdoc CSS rules + #results { + position: initial !important; + overflow: initial !important; + + > table { + margin-bottom: 0 !important; + } + } +} diff --git a/templates/style/rustdoc.scss b/templates/style/rustdoc.scss index a71b6a93e..8a59d5239 100644 --- a/templates/style/rustdoc.scss +++ b/templates/style/rustdoc.scss @@ -1,19 +1,5 @@ // FIXME: Use modules -@import "vars", "navbar", "themes", "fa", "footer"; - -// This rule is needed to be sure that the footer will always be at the bottom of the page. -#rustdoc_body_wrapper { - min-height: calc(100vh - #{$top-navbar-height + $footer-height + 2}); -} - -#clipboard { - cursor: pointer; -} - -// Force the navbar to be left-aligned on rustdoc pages -body.rustdoc-page > .nav-container > .container { - margin-left: 0; -} +@import "rustdoc-common"; div.container-rustdoc { text-align: left; @@ -21,111 +7,18 @@ div.container-rustdoc { > .docs-rs-footer { bottom: -32px; right: -15px; - width: unset; } } -div.container-rustdoc { - width: unset; -} div.container-rustdoc:not(.source) { > .docs-rs-footer { left: 185px; // This is the left sidebar } - - // This is when the rustdoc sidebar "disappears" (for mobile mode). - @media (max-width: 700px) { - > .docs-rs-footer:not(.source) { - left: -15px; - } - } -} - -div.container-rustdoc.source { - > .docs-rs-footer { - left: -15px; - // This is needed because even though the sidebar only contains the header, it still takes - // all the height, going over the footer. - z-index: 1; - } -} - -// this is a super nasty override for help dialog in rustdocs -// see #52 for details -body.blur { - > :not(#help) { - filter: none; - -webkit-filter: none; - } - - > div.nav-container > *, - > div.docsrs-package-container > *, - > div.rustdoc > :not(#help) { - filter: blur(8px); - -webkit-filter: blur(8px); - opacity: 0.7; - } } -// rustdoc overrides div.rustdoc { - $padding-x: 15px; - padding: 10px $padding-x 20px; - position: relative; - - @media (max-width: 700px) { - padding-top: 0; - } - - .sidebar { - @media (min-width: 701px) { - margin-top: $top-navbar-height; - } - - .block > ul > li { - margin-right: -10px; - } - - @media (max-width: 700px) { - margin-left: -2 * $padding-x; // offset the additional padding added by the parent containers - width: calc(100% + #{4 * $padding-x}); - - &.mobile { - top: $top-navbar-height; - margin-left: 0; // since the sidebar is now fixed position, remove the padding workaround - width: 100%; - - .sidebar-elems.show-it { - top: 45px + $top-navbar-height; - } - - #sidebar-filler { - top: $top-navbar-height; - } - } - } - } - - #source-sidebar { - top: $top-navbar-height; - } - #sidebar-toggle { top: 62px; } - - &:focus { - outline: unset; - } - - // Overriding some outdated rustdoc CSS rules - #results { - position: initial !important; - overflow: initial !important; - - > table { - margin-bottom: 0 !important; - } - } }