From d86b829eb382e95c03db4d990978de6527a43574 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 15 Sep 2022 15:42:00 +0200 Subject: [PATCH 1/7] Add version switcher script for std docs --- src/bootstrap/doc.rs | 10 ++ src/doc/switcher.inc | 1 + src/doc/version-switcher.js | 210 ++++++++++++++++++++++++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 src/doc/switcher.inc create mode 100644 src/doc/version-switcher.js diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 819af6587484d..fb51444546707 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -430,13 +430,23 @@ impl Step for Std { t!(fs::create_dir_all(&out)); t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css"))); + let content = fs::read_to_string(builder.src.join("src/doc/version-switcher.js")).unwrap(); + fs::write( + out.join("version-switcher.js"), + content.replace("/* VERSION TO BE REPLACED */", &builder.version), + ) + .unwrap(); + let index_page = builder.src.join("src/doc/index.md").into_os_string(); + let switcher_script = builder.src.join("src/doc/switcher.inc").into_os_string(); let mut extra_args = vec![ OsStr::new("--markdown-css"), OsStr::new("rust.css"), OsStr::new("--markdown-no-toc"), OsStr::new("--index-page"), &index_page, + OsStr::new("--html-in-header"), + &switcher_script, ]; if !builder.config.docs_minification { diff --git a/src/doc/switcher.inc b/src/doc/switcher.inc new file mode 100644 index 0000000000000..133255ab85d4c --- /dev/null +++ b/src/doc/switcher.inc @@ -0,0 +1 @@ + diff --git a/src/doc/version-switcher.js b/src/doc/version-switcher.js new file mode 100644 index 0000000000000..a796876f8113c --- /dev/null +++ b/src/doc/version-switcher.js @@ -0,0 +1,210 @@ +const CURRENT_VERSION = "/* VERSION TO BE REPLACED */"; + +function checkIfIsOldVersion() { + if (["http:", "https:"].indexOf(window.location.protocol) === -1) { + return; + } + const parts = window.location.pathname.split("/"); + + return parts.length > 1 && parts[1].indexOf(".") !== -1 && parts[1] !== CURRENT_VERSION; +} + +function createOption(text, isDefault) { + const option = document.createElement("option"); + option.value = text; + option.innerText = text; + if (isDefault) { + option.selected = true; + } + return option; +} + +function addStyle(css) { + const style = document.createElement("style"); + style.type = "text/css"; + style.appendChild(document.createTextNode(css)); + + document.head.appendChild(style); +} + +function setupStyleFor59(rustdoc_container) { + // nothing to do in here! +} + +function setupStyleFor32(rustdoc_container, switcherEl, extraStyle) { + document.body.style.padding = "0"; + rustdoc_container.style.position = "relative"; + rustdoc_container.style.padding = "0 15px 20px 15px"; + + addStyle(`@media (min-width: 701px) { + .rustdoc { + padding: 10px 15px 20px 15px !important; + } + #switch-version-filler { + display: block !important; + left: 0 !important; + } +} + +.sidebar.mobile { + top: 0 !important; +} +${extraStyle}`); + + // We also need to create a "cosmetic" element to not have a weird empty space above the + // sidebar. + const filler = document.createElement("div"); + filler.style.position = "fixed"; + filler.style.top = "0"; + filler.style.bottom = "0"; + filler.style.zIndex = "-1"; + filler.style.display = "none"; + filler.id = "switch-version-filler"; + document.body.appendChild(filler); + + function changeSidebarTop() { + const height = switcherEl.getBoundingClientRect().height; + const sidebar = document.querySelector(".sidebar"); + sidebar.style.top = height + 1 + "px"; + } + setTimeout(() => { + const sidebar = window.getComputedStyle(document.querySelector(".sidebar")); + filler.style.width = sidebar.width; + filler.style.backgroundColor = sidebar.backgroundColor; + changeSidebarTop(); + }, 0); // it'll be computed once it's added in the DOM. + window.addEventListener("resize", changeSidebarTop); +} + +function setupStyleFor22(rustdoc_container, switcherEl) { + // It's mostly the same as `setupStyleFor32` so we call it and make the extra changes afterward. + setupStyleFor32(rustdoc_container, switcherEl, `@media (max-width: 700px) { + .sidebar { + height: 45px; + min-height: 40px; + margin: 0; + margin-left: -15px; + padding: 0 15px; + position: static; + z-index: 1; + } +}`); +} + +function setupStyleFor21(rustdoc_container, switcherEl) { + // It's mostly the same as `setupStyleFor22` so we call it and make the extra changes afterward. + document.body.style.padding = "0"; + + const css = `.rustdoc { + padding: 10px 15px 20px 15px !important; +}`; + addStyle(css); + + function changeSidebarTop() { + const height = switcherEl.getBoundingClientRect().height; + const sidebar = document.querySelector(".sidebar"); + sidebar.style.top = height + 1 + "px"; + } + setTimeout(() => { + const sidebar = window.getComputedStyle(document.querySelector(".sidebar")); + changeSidebarTop(); + }, 0); // it'll be computed once it's added in the DOM. + window.addEventListener("resize", changeSidebarTop); +} + +function getHtmlForSwitcher(isOldVersion, switcher_container) { + if (!isOldVersion) { + switcher_container.style.color = "#eee"; + return "You can pick a different version with this dropdown: "; + } + + switcher_container.style.color = "#e57300"; + + addStyle(`#doc-version-switcher svg { + width: 1em; + height: 1em; + fill: currentColor; + padding-top: 0.1em; +}`); + + const warning_img = `\ + `; + return warning_img + "You are seeing an outdated version of this documentation. " + + "Click on the dropdown to go to the latest stable version: "; +} + +function showSwitcher(isOldVersion) { + const el = document.createElement("div"); + + el.style.borderBottom = "1px solid #bbb"; + el.style.fontSize = "1.1em"; + el.style.padding = "4px"; + el.style.background = "#111"; + el.style.width = "100%"; + el.id = "doc-version-switcher"; + + const parts = window.location.pathname.split("/"); + parts[1] = "stable"; + const url = parts.join("/"); + + const current_doc_version = window.location.pathname.split("/")[1]; + const version_picker = document.createElement("select"); + + version_picker.appendChild(createOption("stable", false)); + version_picker.appendChild(createOption("beta", false)); + version_picker.appendChild(createOption("nightly", false)); + + const version_parts = CURRENT_VERSION.split("."); + for (let major = parseInt(version_parts[0]); major >= 1; --major) { + for (let medium = parseInt(version_parts[1]); medium >= 0; --medium) { + const version = `${major}.${medium}.0`; + version_picker.appendChild(createOption(version, version === current_doc_version)); + } + } + + version_picker.style.color = "#000"; + version_picker.onchange = (event) => { + const url_parts = window.location.pathname.split("/"); + url_parts[1] = event.target.value; + window.location.href = url_parts.join("/"); + }; + + const span = document.createElement("span"); + span.innerHTML = getHtmlForSwitcher(isOldVersion, el); + span.appendChild(version_picker); + + el.appendChild(span); + + const rustdoc_container = document.createElement("div"); + + let medium_version = current_doc_version.split(".").slice(1, 2); + if (medium_version.length === 0) { + medium_version = ["-1"]; + } + medium_version = parseInt(medium_version[0]); + if (medium_version < 0 || medium_version > 58) { + setupStyleFor59(rustdoc_container, el); + } else if (medium_version > 31) { + setupStyleFor32(rustdoc_container, el, ""); + } else if (medium_version > 21) { + setupStyleFor22(rustdoc_container, el); + } else { + setupStyleFor21(rustdoc_container, el); + } + + rustdoc_container.className = document.body.className; + document.body.className = ""; + while (document.body.childNodes.length > 0) { + rustdoc_container.appendChild(document.body.childNodes[0]); + } + + document.body.appendChild(el); + document.body.appendChild(rustdoc_container); +} + +showSwitcher(checkIfIsOldVersion()); From 810dc9bd84e65351d3ab8a0871e3aaa9e4b52a8e Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 17 Sep 2022 20:08:01 -0400 Subject: [PATCH 2/7] Switch to dev-doc + hardcode nightly temporarily --- src/doc/switcher.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/switcher.inc b/src/doc/switcher.inc index 133255ab85d4c..420dcb5c58ec8 100644 --- a/src/doc/switcher.inc +++ b/src/doc/switcher.inc @@ -1 +1 @@ - + From 96c298246778c6dc17af6a5af3bd6edef7b9c1af Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 18 Sep 2022 15:12:55 +0200 Subject: [PATCH 3/7] * Select the current channel as the default selected version. * Improve bootstrap source code --- src/bootstrap/doc.rs | 7 +++---- src/doc/version-switcher.js | 8 ++++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index fb51444546707..3a347ae011000 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -430,12 +430,11 @@ impl Step for Std { t!(fs::create_dir_all(&out)); t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css"))); - let content = fs::read_to_string(builder.src.join("src/doc/version-switcher.js")).unwrap(); - fs::write( + let content = t!(fs::read_to_string(builder.src.join("src/doc/version-switcher.js"))); + t!(fs::write( out.join("version-switcher.js"), content.replace("/* VERSION TO BE REPLACED */", &builder.version), - ) - .unwrap(); + )); let index_page = builder.src.join("src/doc/index.md").into_os_string(); let switcher_script = builder.src.join("src/doc/switcher.inc").into_os_string(); diff --git a/src/doc/version-switcher.js b/src/doc/version-switcher.js index a796876f8113c..58073d58b21f1 100644 --- a/src/doc/version-switcher.js +++ b/src/doc/version-switcher.js @@ -2,7 +2,7 @@ const CURRENT_VERSION = "/* VERSION TO BE REPLACED */"; function checkIfIsOldVersion() { if (["http:", "https:"].indexOf(window.location.protocol) === -1) { - return; + return false; } const parts = window.location.pathname.split("/"); @@ -155,9 +155,9 @@ function showSwitcher(isOldVersion) { const current_doc_version = window.location.pathname.split("/")[1]; const version_picker = document.createElement("select"); - version_picker.appendChild(createOption("stable", false)); - version_picker.appendChild(createOption("beta", false)); - version_picker.appendChild(createOption("nightly", false)); + version_picker.appendChild(createOption("stable", current_doc_version === "stable")); + version_picker.appendChild(createOption("beta", current_doc_version === "beta")); + version_picker.appendChild(createOption("nightly", current_doc_version === "nightly")); const version_parts = CURRENT_VERSION.split("."); for (let major = parseInt(version_parts[0]); major >= 1; --major) { From b174ed1c7e900c563853b9801d7356363abd3637 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 21 Sep 2022 17:25:56 +0200 Subject: [PATCH 4/7] Correctly compute the maximum existing doc version --- src/bootstrap/doc.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 3a347ae011000..2f686a8dddded 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -11,6 +11,7 @@ use std::ffi::OsStr; use std::fs; use std::io; use std::path::{Path, PathBuf}; +use std::str::FromStr; use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; @@ -400,6 +401,18 @@ impl Step for Standalone { } } +fn get_doc_max_version(builder: &Builder<'_>) -> String { + let reduce_by = match builder.config.channel.as_str() { + "dev" => 3, + "nightly" => 2, + "beta" => 1, + _ => 0, + }; + let parts = builder.version.split(".").collect::>(); + let medium = t!(u32::from_str(parts[1])); + format!("{}.{}.{}", parts[0], medium - reduce_by, parts[2..].join(".")) +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Std { pub stage: u32, @@ -430,10 +443,12 @@ impl Step for Std { t!(fs::create_dir_all(&out)); t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css"))); + let version = get_doc_max_version(&builder); + let content = t!(fs::read_to_string(builder.src.join("src/doc/version-switcher.js"))); t!(fs::write( out.join("version-switcher.js"), - content.replace("/* VERSION TO BE REPLACED */", &builder.version), + content.replace("/* VERSION TO BE REPLACED */", &version), )); let index_page = builder.src.join("src/doc/index.md").into_os_string(); From 74af1afc6c766ce851fb3b51588c2dbaa508f4dc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 21 Sep 2022 17:47:26 +0200 Subject: [PATCH 5/7] Simplify distribution of version-switcher.js --- src/bootstrap/doc.rs | 22 +++------------------- src/doc/version-switcher.js | 30 +++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 2f686a8dddded..d6cc01232a7dd 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -11,7 +11,6 @@ use std::ffi::OsStr; use std::fs; use std::io; use std::path::{Path, PathBuf}; -use std::str::FromStr; use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; @@ -401,18 +400,6 @@ impl Step for Standalone { } } -fn get_doc_max_version(builder: &Builder<'_>) -> String { - let reduce_by = match builder.config.channel.as_str() { - "dev" => 3, - "nightly" => 2, - "beta" => 1, - _ => 0, - }; - let parts = builder.version.split(".").collect::>(); - let medium = t!(u32::from_str(parts[1])); - format!("{}.{}.{}", parts[0], medium - reduce_by, parts[2..].join(".")) -} - #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Std { pub stage: u32, @@ -443,12 +430,9 @@ impl Step for Std { t!(fs::create_dir_all(&out)); t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css"))); - let version = get_doc_max_version(&builder); - - let content = t!(fs::read_to_string(builder.src.join("src/doc/version-switcher.js"))); - t!(fs::write( - out.join("version-switcher.js"), - content.replace("/* VERSION TO BE REPLACED */", &version), + t!(fs::copy( + builder.src.join("src/doc/version-switcher.js"), + out.join("version-switcher.js") )); let index_page = builder.src.join("src/doc/index.md").into_os_string(); diff --git a/src/doc/version-switcher.js b/src/doc/version-switcher.js index 58073d58b21f1..2dc5dda31bcee 100644 --- a/src/doc/version-switcher.js +++ b/src/doc/version-switcher.js @@ -1,4 +1,21 @@ -const CURRENT_VERSION = "/* VERSION TO BE REPLACED */"; +(function() { + +let CURRENT_VERSION = -1; + +function get_current_version() { + if (CURRENT_VERSION !== -1) { + return CURRENT_VERSION; + } + const now = Date.now(); + // Month is 0-indexed. + // First release of Rust, 15 may 2015. + const first_release = new Date(2015, 4, 15); + const diff_time = Math.abs(now - first_release); + const nb_days = Math.ceil(diff_time / (1000 * 60 * 60 * 24)); + const nb_weeks = nb_days / 7; + CURRENT_VERSION = Math.floor(nb_weeks / 6); + return CURRENT_VERSION; +} function checkIfIsOldVersion() { if (["http:", "https:"].indexOf(window.location.protocol) === -1) { @@ -159,12 +176,9 @@ function showSwitcher(isOldVersion) { version_picker.appendChild(createOption("beta", current_doc_version === "beta")); version_picker.appendChild(createOption("nightly", current_doc_version === "nightly")); - const version_parts = CURRENT_VERSION.split("."); - for (let major = parseInt(version_parts[0]); major >= 1; --major) { - for (let medium = parseInt(version_parts[1]); medium >= 0; --medium) { - const version = `${major}.${medium}.0`; - version_picker.appendChild(createOption(version, version === current_doc_version)); - } + for (let medium = get_current_version(); medium >= 0; --medium) { + const version = `1.${medium}.0`; + version_picker.appendChild(createOption(version, version === current_doc_version)); } version_picker.style.color = "#000"; @@ -208,3 +222,5 @@ function showSwitcher(isOldVersion) { } showSwitcher(checkIfIsOldVersion()); + +}()); From 7e37ea1b4a51196ca39847429cdc31e741350f0e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 27 Sep 2022 22:57:01 +0200 Subject: [PATCH 6/7] Revert order of nightly/beta/stable --- src/doc/version-switcher.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/version-switcher.js b/src/doc/version-switcher.js index 2dc5dda31bcee..87ce6f5991ad2 100644 --- a/src/doc/version-switcher.js +++ b/src/doc/version-switcher.js @@ -172,9 +172,9 @@ function showSwitcher(isOldVersion) { const current_doc_version = window.location.pathname.split("/")[1]; const version_picker = document.createElement("select"); - version_picker.appendChild(createOption("stable", current_doc_version === "stable")); - version_picker.appendChild(createOption("beta", current_doc_version === "beta")); version_picker.appendChild(createOption("nightly", current_doc_version === "nightly")); + version_picker.appendChild(createOption("beta", current_doc_version === "beta")); + version_picker.appendChild(createOption("stable", current_doc_version === "stable")); for (let medium = get_current_version(); medium >= 0; --medium) { const version = `1.${medium}.0`; From d8aff436ee4cd384e1d47f0d591f27c0700c7e7a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 27 Sep 2022 23:29:08 +0200 Subject: [PATCH 7/7] Fix sidebar button position for doc versions newer than 60 --- src/doc/version-switcher.js | 51 ++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/doc/version-switcher.js b/src/doc/version-switcher.js index 87ce6f5991ad2..94a84deda2bd6 100644 --- a/src/doc/version-switcher.js +++ b/src/doc/version-switcher.js @@ -44,8 +44,50 @@ function addStyle(css) { document.head.appendChild(style); } -function setupStyleFor59(rustdoc_container) { - // nothing to do in here! +function setupStyleFor60(rustdoc_container, switcherEl) { + function changeSidebarTop() { + const height = switcherEl.getBoundingClientRect().height; + const sidebarTopbar = document.querySelector(".mobile-topbar"); + const sidebarTopbarHeight = sidebarTopbar.getBoundingClientRect().height; + const sidebar = document.querySelector(".sidebar"); + sidebar.style.top = height + sidebarTopbarHeight + 1 + "px"; + } + setTimeout(() => { + changeSidebarTop(); + }, 0); // it'll be computed once it's added in the DOM. + window.addEventListener("resize", changeSidebarTop); +} + +function setupStyleFor59(rustdoc_container, switcherEl) { + function changeSidebarTop() { + const height = switcherEl.getBoundingClientRect().height; + document.body.marginTop = height + 1 + "px"; + const sidebarButton = document.querySelector(".sidebar-menu"); + const val = sidebarButton.getAttribute("old-top"); + if (val === null) { + // We update the position directly. + sidebarButton.style.top = height + 1 + "px"; + } else { + // We update the attribute value. + sidebarButton.setAttribute("old-top", height + 1 + "px"); + } + } + setTimeout(() => { + changeSidebarTop(); + }, 0); // it'll be computed once it's added in the DOM. + window.addEventListener("resize", changeSidebarTop); + document.querySelector(".sidebar-menu").addEventListener("click", () => { + const sidebarButton = document.querySelector(".sidebar-menu"); + const val = sidebarButton.getAttribute("old-top"); + if (val === null) { + const height = switcherEl.getBoundingClientRect().height; + sidebarButton.setAttribute("old-top", sidebarButton.style.top); + sidebarButton.style.top = "0"; + } else { + sidebarButton.style.top = val; + sidebarButton.removeAttribute("old-top"); + } + }); } function setupStyleFor32(rustdoc_container, switcherEl, extraStyle) { @@ -123,7 +165,6 @@ function setupStyleFor21(rustdoc_container, switcherEl) { sidebar.style.top = height + 1 + "px"; } setTimeout(() => { - const sidebar = window.getComputedStyle(document.querySelector(".sidebar")); changeSidebarTop(); }, 0); // it'll be computed once it's added in the DOM. window.addEventListener("resize", changeSidebarTop); @@ -201,7 +242,9 @@ function showSwitcher(isOldVersion) { medium_version = ["-1"]; } medium_version = parseInt(medium_version[0]); - if (medium_version < 0 || medium_version > 58) { + if (medium_version < 0 || medium_version > 59) { + setupStyleFor60(rustdoc_container, el); + } else if (medium_version > 58) { setupStyleFor59(rustdoc_container, el); } else if (medium_version > 31) { setupStyleFor32(rustdoc_container, el, "");