mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-12 06:53:05 +00:00
Auto merge of #56005 - GuillaumeGomez:speedup-doc-render, r=QuietMisdreavus
Greatly improve rustdoc rendering speed issues Fixes #55900. So a few improvements here: * we're switching to `DOMTokenList` API when available providing a replacement if it isn't (should only happen on safari and IE I think...) * hide doc sections by default to allow the whole HTML generation to happen in the background to avoid triggering DOM redraw all the times (which killed the performances) r? @QuietMisdreavus
This commit is contained in:
commit
7f04a646c6
@ -54,6 +54,7 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
|
||||
<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}light{suffix}.css\" \
|
||||
id=\"themeStyle\">\
|
||||
<script src=\"{root_path}storage{suffix}.js\"></script>\
|
||||
<noscript><link rel=\"stylesheet\" href=\"{root_path}noscript{suffix}.css\"></noscript>\
|
||||
{css_extension}\
|
||||
{favicon}\
|
||||
{in_header}\
|
||||
|
@ -772,6 +772,9 @@ fn write_shared(
|
||||
write_minify(cx.dst.join(&format!("settings{}.css", cx.shared.resource_suffix)),
|
||||
static_files::SETTINGS_CSS,
|
||||
options.enable_minification)?;
|
||||
write_minify(cx.dst.join(&format!("noscript{}.css", cx.shared.resource_suffix)),
|
||||
static_files::NOSCRIPT_CSS,
|
||||
options.enable_minification)?;
|
||||
|
||||
// To avoid "light.css" to be overwritten, we'll first run over the received themes and only
|
||||
// then we'll run over the "official" styles.
|
||||
@ -865,9 +868,8 @@ themePicker.onblur = handleThemeButtonsBlur;
|
||||
}
|
||||
|
||||
{
|
||||
let mut data = format!("var resourcesSuffix = \"{}\";\n",
|
||||
cx.shared.resource_suffix);
|
||||
data.push_str(static_files::STORAGE_JS);
|
||||
let mut data = static_files::STORAGE_JS.to_owned();
|
||||
data.push_str(&format!("var resourcesSuffix = \"{}\";", cx.shared.resource_suffix));
|
||||
write_minify(cx.dst.join(&format!("storage{}.js", cx.shared.resource_suffix)),
|
||||
&data,
|
||||
options.enable_minification)?;
|
||||
@ -3013,6 +3015,22 @@ fn item_trait(
|
||||
// Trait documentation
|
||||
document(w, cx, it)?;
|
||||
|
||||
fn write_small_section_header(
|
||||
w: &mut fmt::Formatter,
|
||||
id: &str,
|
||||
title: &str,
|
||||
extra_content: &str,
|
||||
) -> fmt::Result {
|
||||
write!(w, "
|
||||
<h2 id='{0}' class='small-section-header'>\
|
||||
{1}<a href='#{0}' class='anchor'></a>\
|
||||
</h2>{2}", id, title, extra_content)
|
||||
}
|
||||
|
||||
fn write_loading_content(w: &mut fmt::Formatter, extra_content: &str) -> fmt::Result {
|
||||
write!(w, "{}<span class='loading-content'>Loading content...</span>", extra_content)
|
||||
}
|
||||
|
||||
fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::Item)
|
||||
-> fmt::Result {
|
||||
let name = m.name.as_ref().unwrap();
|
||||
@ -3033,74 +3051,45 @@ fn item_trait(
|
||||
}
|
||||
|
||||
if !types.is_empty() {
|
||||
write!(w, "
|
||||
<h2 id='associated-types' class='small-section-header'>
|
||||
Associated Types<a href='#associated-types' class='anchor'></a>
|
||||
</h2>
|
||||
<div class='methods'>
|
||||
")?;
|
||||
write_small_section_header(w, "associated-types", "Associated Types",
|
||||
"<div class='methods'>")?;
|
||||
for t in &types {
|
||||
trait_item(w, cx, *t, it)?;
|
||||
}
|
||||
write!(w, "</div>")?;
|
||||
write_loading_content(w, "</div>")?;
|
||||
}
|
||||
|
||||
if !consts.is_empty() {
|
||||
write!(w, "
|
||||
<h2 id='associated-const' class='small-section-header'>
|
||||
Associated Constants<a href='#associated-const' class='anchor'></a>
|
||||
</h2>
|
||||
<div class='methods'>
|
||||
")?;
|
||||
write_small_section_header(w, "associated-const", "Associated Constants",
|
||||
"<div class='methods'>")?;
|
||||
for t in &consts {
|
||||
trait_item(w, cx, *t, it)?;
|
||||
}
|
||||
write!(w, "</div>")?;
|
||||
write_loading_content(w, "</div>")?;
|
||||
}
|
||||
|
||||
// Output the documentation for each function individually
|
||||
if !required.is_empty() {
|
||||
write!(w, "
|
||||
<h2 id='required-methods' class='small-section-header'>
|
||||
Required Methods<a href='#required-methods' class='anchor'></a>
|
||||
</h2>
|
||||
<div class='methods'>
|
||||
")?;
|
||||
write_small_section_header(w, "required-methods", "Required methods",
|
||||
"<div class='methods'>")?;
|
||||
for m in &required {
|
||||
trait_item(w, cx, *m, it)?;
|
||||
}
|
||||
write!(w, "</div>")?;
|
||||
write_loading_content(w, "</div>")?;
|
||||
}
|
||||
if !provided.is_empty() {
|
||||
write!(w, "
|
||||
<h2 id='provided-methods' class='small-section-header'>
|
||||
Provided Methods<a href='#provided-methods' class='anchor'></a>
|
||||
</h2>
|
||||
<div class='methods'>
|
||||
")?;
|
||||
write_small_section_header(w, "provided-methods", "Provided methods",
|
||||
"<div class='methods'>")?;
|
||||
for m in &provided {
|
||||
trait_item(w, cx, *m, it)?;
|
||||
}
|
||||
write!(w, "</div>")?;
|
||||
write_loading_content(w, "</div>")?;
|
||||
}
|
||||
|
||||
// If there are methods directly on this trait object, render them here.
|
||||
render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)?;
|
||||
|
||||
let cache = cache();
|
||||
let impl_header = "\
|
||||
<h2 id='implementors' class='small-section-header'>\
|
||||
Implementors<a href='#implementors' class='anchor'></a>\
|
||||
</h2>\
|
||||
<div class='item-list' id='implementors-list'>\
|
||||
";
|
||||
|
||||
let synthetic_impl_header = "\
|
||||
<h2 id='synthetic-implementors' class='small-section-header'>\
|
||||
Auto implementors<a href='#synthetic-implementors' class='anchor'></a>\
|
||||
</h2>\
|
||||
<div class='item-list' id='synthetic-implementors-list'>\
|
||||
";
|
||||
|
||||
let mut synthetic_types = Vec::new();
|
||||
|
||||
@ -3137,11 +3126,7 @@ fn item_trait(
|
||||
concrete.sort_by(compare_impl);
|
||||
|
||||
if !foreign.is_empty() {
|
||||
write!(w, "
|
||||
<h2 id='foreign-impls' class='small-section-header'>
|
||||
Implementations on Foreign Types<a href='#foreign-impls' class='anchor'></a>
|
||||
</h2>
|
||||
")?;
|
||||
write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "")?;
|
||||
|
||||
for implementor in foreign {
|
||||
let assoc_link = AssocItemLink::GotoSource(
|
||||
@ -3152,33 +3137,38 @@ fn item_trait(
|
||||
RenderMode::Normal, implementor.impl_item.stable_since(), false,
|
||||
None)?;
|
||||
}
|
||||
write_loading_content(w, "")?;
|
||||
}
|
||||
|
||||
write!(w, "{}", impl_header)?;
|
||||
write_small_section_header(w, "implementors", "Implementors",
|
||||
"<div class='item-list' id='implementors-list'>")?;
|
||||
for implementor in concrete {
|
||||
render_implementor(cx, implementor, w, &implementor_dups)?;
|
||||
}
|
||||
write!(w, "</div>")?;
|
||||
write_loading_content(w, "</div>")?;
|
||||
|
||||
if t.auto {
|
||||
write!(w, "{}", synthetic_impl_header)?;
|
||||
write_small_section_header(w, "synthetic-implementors", "Auto implementors",
|
||||
"<div class='item-list' id='synthetic-implementors-list'>")?;
|
||||
for implementor in synthetic {
|
||||
synthetic_types.extend(
|
||||
collect_paths_for_type(implementor.inner_impl().for_.clone())
|
||||
);
|
||||
render_implementor(cx, implementor, w, &implementor_dups)?;
|
||||
}
|
||||
write!(w, "</div>")?;
|
||||
write_loading_content(w, "</div>")?;
|
||||
}
|
||||
} else {
|
||||
// even without any implementations to write in, we still want the heading and list, so the
|
||||
// implementors javascript file pulled in below has somewhere to write the impls into
|
||||
write!(w, "{}", impl_header)?;
|
||||
write!(w, "</div>")?;
|
||||
write_small_section_header(w, "implementors", "Implementors",
|
||||
"<div class='item-list' id='implementors-list'>")?;
|
||||
write_loading_content(w, "</div>")?;
|
||||
|
||||
if t.auto {
|
||||
write!(w, "{}", synthetic_impl_header)?;
|
||||
write!(w, "</div>")?;
|
||||
write_small_section_header(w, "synthetic-implementors", "Auto implementors",
|
||||
"<div class='item-list' id='synthetic-implementors-list'>")?;
|
||||
write_loading_content(w, "</div>")?;
|
||||
}
|
||||
}
|
||||
write!(w, r#"<script type="text/javascript">window.inlined_types=new Set({});</script>"#,
|
||||
|
File diff suppressed because it is too large
Load Diff
19
src/librustdoc/html/static/noscript.css
Normal file
19
src/librustdoc/html/static/noscript.css
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
* file at the top-level directory of this distribution and at
|
||||
* http://rust-lang.org/COPYRIGHT.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
* http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
* <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
* option. This file may not be copied, modified, or distributed
|
||||
* except according to those terms.
|
||||
*/
|
||||
|
||||
#main > h2 + div, #main > h2 + h3, #main > h3 + div {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.loading-content {
|
||||
display: none;
|
||||
}
|
@ -368,6 +368,10 @@ body:not(.source) .example-wrap > pre {
|
||||
#main > .docblock h2 { font-size: 1.15em; }
|
||||
#main > .docblock h3, #main > .docblock h4, #main > .docblock h5 { font-size: 1em; }
|
||||
|
||||
#main > h2 + div, #main > h2 + h3, #main > h3 + div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.docblock h1 { font-size: 1em; }
|
||||
.docblock h2 { font-size: 0.95em; }
|
||||
.docblock h3, .docblock h4, .docblock h5 { font-size: 0.9em; }
|
||||
|
@ -19,55 +19,38 @@ var mainTheme = document.getElementById("mainThemeStyle");
|
||||
var savedHref = [];
|
||||
|
||||
function hasClass(elem, className) {
|
||||
if (elem && className && elem.className) {
|
||||
var elemClass = elem.className;
|
||||
var start = elemClass.indexOf(className);
|
||||
if (start === -1) {
|
||||
return false;
|
||||
} else if (elemClass.length === className.length) {
|
||||
return true;
|
||||
} else {
|
||||
if (start > 0 && elemClass[start - 1] !== ' ') {
|
||||
return false;
|
||||
}
|
||||
var end = start + className.length;
|
||||
return !(end < elemClass.length && elemClass[end] !== ' ');
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return elem && elem.classList && elem.classList.contains(className);
|
||||
}
|
||||
|
||||
function addClass(elem, className) {
|
||||
if (elem && className && !hasClass(elem, className)) {
|
||||
if (elem.className && elem.className.length > 0) {
|
||||
elem.className += ' ' + className;
|
||||
} else {
|
||||
elem.className = className;
|
||||
}
|
||||
if (!elem || !elem.classList) {
|
||||
return;
|
||||
}
|
||||
elem.classList.add(className);
|
||||
}
|
||||
|
||||
function removeClass(elem, className) {
|
||||
if (elem && className && elem.className) {
|
||||
elem.className = (" " + elem.className + " ").replace(" " + className + " ", " ")
|
||||
.trim();
|
||||
if (!elem || !elem.classList) {
|
||||
return;
|
||||
}
|
||||
elem.classList.remove(className);
|
||||
}
|
||||
|
||||
function isHidden(elem) {
|
||||
return (elem.offsetParent === null)
|
||||
return elem.offsetParent === null;
|
||||
}
|
||||
|
||||
function onEach(arr, func, reversed) {
|
||||
if (arr && arr.length > 0 && func) {
|
||||
var length = arr.length;
|
||||
if (reversed !== true) {
|
||||
for (var i = 0; i < arr.length; ++i) {
|
||||
for (var i = 0; i < length; ++i) {
|
||||
if (func(arr[i]) === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var i = arr.length - 1; i >= 0; --i) {
|
||||
for (var i = length - 1; i >= 0; --i) {
|
||||
if (func(arr[i]) === true) {
|
||||
return true;
|
||||
}
|
||||
@ -77,6 +60,13 @@ function onEach(arr, func, reversed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function onEachLazy(lazyArray, func, reversed) {
|
||||
return onEach(
|
||||
Array.prototype.slice.call(lazyArray),
|
||||
func,
|
||||
reversed);
|
||||
}
|
||||
|
||||
function usableLocalStorage() {
|
||||
// Check if the browser supports localStorage at all:
|
||||
if (typeof(Storage) === "undefined") {
|
||||
@ -133,8 +123,8 @@ function switchTheme(styleElem, mainStyleElem, newTheme) {
|
||||
});
|
||||
if (found === true) {
|
||||
styleElem.href = newHref;
|
||||
updateLocalStorage('rustdoc-theme', newTheme);
|
||||
updateLocalStorage("rustdoc-theme", newTheme);
|
||||
}
|
||||
}
|
||||
|
||||
switchTheme(currentTheme, mainTheme, getCurrentValue('rustdoc-theme') || 'light');
|
||||
switchTheme(currentTheme, mainTheme, getCurrentValue("rustdoc-theme") || "light");
|
||||
|
@ -23,6 +23,9 @@ pub static RUSTDOC_CSS: &'static str = include_str!("static/rustdoc.css");
|
||||
/// The file contents of `settings.css`, responsible for the items on the settings page.
|
||||
pub static SETTINGS_CSS: &'static str = include_str!("static/settings.css");
|
||||
|
||||
/// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled.
|
||||
pub static NOSCRIPT_CSS: &'static str = include_str!("static/noscript.css");
|
||||
|
||||
/// The file contents of `normalize.css`, included to even out standard elements between browser
|
||||
/// implementations.
|
||||
pub static NORMALIZE_CSS: &'static str = include_str!("static/normalize.css");
|
||||
|
Loading…
Reference in New Issue
Block a user