diff options
| -rw-r--r-- | src/librustdoc/html/render/context.rs | 28 | ||||
| -rw-r--r-- | src/librustdoc/html/static/js/main.js | 39 | ||||
| -rw-r--r-- | src/librustdoc/html/static/js/storage.js | 46 | ||||
| -rw-r--r-- | src/librustdoc/html/templates/page.html | 39 |
4 files changed, 99 insertions, 53 deletions
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 5e4a595627b..ea5a4590f33 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -649,11 +649,35 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { </noscript>\ <link rel=\"stylesheet\" \ href=\"{static_root_path}{settings_css}\">\ - <script defer src=\"{static_root_path}{settings_js}\"></script>", + <script defer src=\"{static_root_path}{settings_js}\"></script>\ + <link rel=\"preload\" href=\"{static_root_path}{theme_light_css}\" \ + as=\"style\">\ + <link rel=\"preload\" href=\"{static_root_path}{theme_dark_css}\" \ + as=\"style\">\ + <link rel=\"preload\" href=\"{static_root_path}{theme_ayu_css}\" \ + as=\"style\">", static_root_path = page.get_static_root_path(), settings_css = static_files::STATIC_FILES.settings_css, settings_js = static_files::STATIC_FILES.settings_js, - ) + theme_light_css = static_files::STATIC_FILES.theme_light_css, + theme_dark_css = static_files::STATIC_FILES.theme_dark_css, + theme_ayu_css = static_files::STATIC_FILES.theme_ayu_css, + ); + // Pre-load all theme CSS files, so that switching feels seamless. + // + // When loading settings.html as a popover, the equivalent HTML is + // generated in main.js. + for file in &shared.style_files { + if let Ok(theme) = file.basename() { + write!( + buf, + "<link rel=\"preload\" href=\"{root_path}{theme}{suffix}.css\" \ + as=\"style\">", + root_path = page.static_root_path.unwrap_or(""), + suffix = page.resource_suffix, + ); + } + } }, &shared.style_files, ); diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 5e8c0e8d10c..403b5004d65 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1,20 +1,9 @@ // Local js definitions: /* global addClass, getSettingValue, hasClass, searchState */ -/* global onEach, onEachLazy, removeClass */ +/* global onEach, onEachLazy, removeClass, getVar */ "use strict"; -// Get a value from the rustdoc-vars div, which is used to convey data from -// Rust to the JS. If there is no such element, return null. -function getVar(name) { - const el = document.getElementById("rustdoc-vars"); - if (el) { - return el.attributes["data-" + name].value; - } else { - return null; - } -} - // Given a basename (e.g. "storage") and an extension (e.g. ".js"), return a URL // for a resource under the root-path, with the resource-suffix. function resourcePath(basename, extension) { @@ -187,6 +176,15 @@ function loadCss(cssUrl) { document.getElementsByTagName("head")[0].appendChild(link); } +function preLoadCss(cssUrl) { + // https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload + const link = document.createElement("link"); + link.href = cssUrl; + link.rel = "preload"; + link.as = "style"; + document.getElementsByTagName("head")[0].appendChild(link); +} + (function() { const isHelpPage = window.location.pathname.endsWith("/help.html"); @@ -207,6 +205,23 @@ function loadCss(cssUrl) { // hopefully be loaded when the JS will generate the settings content. loadCss(getVar("static-root-path") + getVar("settings-css")); loadScript(getVar("static-root-path") + getVar("settings-js")); + preLoadCss(getVar("static-root-path") + getVar("theme-light-css")); + preLoadCss(getVar("static-root-path") + getVar("theme-dark-css")); + preLoadCss(getVar("static-root-path") + getVar("theme-ayu-css")); + // Pre-load all theme CSS files, so that switching feels seamless. + // + // When loading settings.html as a standalone page, the equivalent HTML is + // generated in context.rs. + setTimeout(() => { + const themes = getVar("themes").split(","); + for (const theme of themes) { + // if there are no themes, do nothing + // "".split(",") == [""] + if (theme !== "") { + preLoadCss(getVar("root-path") + theme + ".css"); + } + } + }, 0); }; window.searchState = { diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index c72ac254fc0..1e16f34a3eb 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -7,7 +7,6 @@ const darkThemes = ["dark", "ayu"]; window.currentTheme = document.getElementById("themeStyle"); -window.mainTheme = document.getElementById("mainThemeStyle"); // WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY // If you update this line, then you also need to update the media query with the same @@ -44,8 +43,6 @@ function getSettingValue(settingName) { const localStoredTheme = getSettingValue("theme"); -const savedHref = []; - // eslint-disable-next-line no-unused-vars function hasClass(elem, className) { return elem && elem.classList && elem.classList.contains(className); @@ -125,30 +122,37 @@ function getCurrentValue(name) { } } -function switchTheme(styleElem, mainStyleElem, newThemeName, saveTheme) { +// Get a value from the rustdoc-vars div, which is used to convey data from +// Rust to the JS. If there is no such element, return null. +const getVar = (function getVar(name) { + const el = document.getElementById("rustdoc-vars"); + if (el) { + return el.attributes["data-" + name].value; + } else { + return null; + } +}); + +function switchTheme(newThemeName, saveTheme) { // If this new value comes from a system setting or from the previously // saved theme, no need to save it. if (saveTheme) { updateLocalStorage("theme", newThemeName); } - if (savedHref.length === 0) { - onEachLazy(document.getElementsByTagName("link"), el => { - savedHref.push(el.href); - }); + let newHref; + + if (newThemeName === "light" || newThemeName === "dark" || newThemeName === "ayu") { + newHref = getVar("static-root-path") + getVar("theme-" + newThemeName + "-css"); + } else { + newHref = getVar("root-path") + newThemeName + getVar("resource-suffix") + ".css"; } - const newHref = savedHref.find(url => { - const m = url.match(/static\.files\/(.*)-[a-f0-9]{16}\.css$/); - if (m && m[1] === newThemeName) { - return true; - } - const m2 = url.match(/\/([^/]*)\.css$/); - if (m2 && m2[1].startsWith(newThemeName)) { - return true; - } - }); - if (newHref && newHref !== styleElem.href) { - styleElem.href = newHref; + + if (!window.currentTheme) { + document.write("<link rel=\"stylesheet\" id=\"themeStyle\" href=\"" + newHref + "\">"); + window.currentTheme = document.getElementById("themeStyle"); + } else if (newHref !== window.currentTheme.href) { + window.currentTheme.href = newHref; } } @@ -164,7 +168,7 @@ const updateTheme = (function() { */ function updateTheme() { const use = (theme, saveTheme) => { - switchTheme(window.currentTheme, window.mainTheme, theme, saveTheme); + switchTheme(theme, saveTheme); }; // maybe the user has disabled the setting in the meantime! diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index e896850fab6..532660e3d33 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -17,12 +17,6 @@ <link rel="stylesheet" {#+ #} href="{{static_root_path|safe}}{{files.rustdoc_css}}" {#+ #} id="mainThemeStyle"> {# #} - <link rel="stylesheet" id="themeStyle" href="{{static_root_path|safe}}{{files.theme_light_css}}"> {# #} - <link rel="stylesheet" disabled href="{{static_root_path|safe}}{{files.theme_dark_css}}"> {# #} - <link rel="stylesheet" disabled href="{{static_root_path|safe}}{{files.theme_ayu_css}}"> {# #} - {% for theme in themes %} - <link rel="stylesheet" disabled href="{{page.root_path|safe}}{{theme}}{{page.resource_suffix}}.css"> {# #} - {% endfor %} {% if !layout.default_settings.is_empty() %} <script id="default-settings" {#+ #} {%~ for (k, v) in layout.default_settings ~%} @@ -30,6 +24,21 @@ {% endfor %} ></script> {# #} {% endif %} + <div id="rustdoc-vars" {#+ #} + data-root-path="{{page.root_path|safe}}" {#+ #} + data-static-root-path="{{static_root_path|safe}}" {#+ #} + data-current-crate="{{layout.krate}}" {#+ #} + data-themes="{{themes|join(",") }}" {#+ #} + data-resource-suffix="{{page.resource_suffix}}" {#+ #} + data-rustdoc-version="{{rustdoc_version}}" {#+ #} + data-search-js="{{files.search_js}}" {#+ #} + data-settings-js="{{files.settings_js}}" {#+ #} + data-settings-css="{{files.settings_css}}" {#+ #} + data-theme-light-css="{{files.theme_light_css}}" {#+ #} + data-theme-dark-css="{{files.theme_dark_css}}" {#+ #} + data-theme-ayu-css="{{files.theme_ayu_css}}" {#+ #} + > {# #} + </div> {# #} <script src="{{static_root_path|safe}}{{files.storage_js}}"></script> {# #} {% if page.css_class.contains("crate") %} <script defer src="{{page.root_path|safe}}crates{{page.resource_suffix}}.js"></script> {# #} @@ -45,6 +54,12 @@ {% endif %} <noscript> {# #} <link rel="stylesheet" {#+ #} + media="(prefers-color-scheme:light)" {#+ #} + href="{{static_root_path|safe}}{{files.theme_light_css}}"> {# #} + <link rel="stylesheet" {#+ #} + media="(prefers-color-scheme:dark)" {#+ #} + href="{{static_root_path|safe}}{{files.theme_dark_css}}"> {# #} + <link rel="stylesheet" {#+ #} href="{{static_root_path|safe}}{{files.noscript_css}}"> {# #} </noscript> {# #} {% if layout.css_file_extension.is_some() %} @@ -132,17 +147,5 @@ {% if page.css_class != "source" %}</div>{% endif %} </main> {# #} {{ layout.external_html.after_content|safe }} - <div id="rustdoc-vars" {#+ #} - data-root-path="{{page.root_path|safe}}" {#+ #} - data-static-root-path="{{static_root_path|safe}}" {#+ #} - data-current-crate="{{layout.krate}}" {#+ #} - data-themes="{{themes|join(",") }}" {#+ #} - data-resource-suffix="{{page.resource_suffix}}" {#+ #} - data-rustdoc-version="{{rustdoc_version}}" {#+ #} - data-search-js="{{files.search_js}}" {#+ #} - data-settings-js="{{files.settings_js}}" {#+ #} - data-settings-css="{{files.settings_css}}" {#+ #} - > {# #} - </div> {# #} </body> {# #} </html> {# #} |
