Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 371100b

Browse files
committedNov 5, 2022
Auto merge of rust-lang#104017 - matthiaskrgr:rollup-k8i0j9m, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - rust-lang#101702 (rustdoc: add hash to filename of toolchain files) - rust-lang#103920 (Move browser opening logic in `Builder`) - rust-lang#103927 (Do not make typo suggestions when suggesting pattern matching) - rust-lang#103972 (Remove an option and choose a behaviour-preserving default instead.) - rust-lang#103988 (Fix search result bottom border color) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 6b8d9dd + e51e4a4 commit 371100b

File tree

28 files changed

+372
-553
lines changed

28 files changed

+372
-553
lines changed
 

‎compiler/rustc_hir_analysis/src/astconv/mod.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
274274
item_segment.args(),
275275
item_segment.infer_args,
276276
None,
277-
None,
277+
ty::BoundConstness::NotConst,
278278
);
279279
if let Some(b) = item_segment.args().bindings.first() {
280280
Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
@@ -324,7 +324,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
324324
generic_args: &'a hir::GenericArgs<'_>,
325325
infer_args: bool,
326326
self_ty: Option<Ty<'tcx>>,
327-
constness: Option<ty::BoundConstness>,
327+
constness: ty::BoundConstness,
328328
) -> (SubstsRef<'tcx>, GenericArgCountResult) {
329329
// If the type is parameterized by this region, then replace this
330330
// region with the current anon region binding (in other words,
@@ -538,7 +538,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
538538
&mut substs_ctx,
539539
);
540540

541-
if let Some(ty::BoundConstness::ConstIfConst) = constness
541+
if let ty::BoundConstness::ConstIfConst = constness
542542
&& generics.has_self && !tcx.has_attr(def_id, sym::const_trait)
543543
{
544544
tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span } );
@@ -611,7 +611,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
611611
item_segment.args(),
612612
item_segment.infer_args,
613613
None,
614-
None,
614+
ty::BoundConstness::NotConst,
615615
);
616616

617617
if let Some(b) = item_segment.args().bindings.first() {
@@ -641,7 +641,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
641641
self_ty,
642642
trait_ref.path.segments.last().unwrap(),
643643
true,
644-
Some(constness),
644+
constness,
645645
)
646646
}
647647

@@ -668,7 +668,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
668668
args,
669669
infer_args,
670670
Some(self_ty),
671-
Some(constness),
671+
constness,
672672
);
673673

674674
let tcx = self.tcx();
@@ -798,7 +798,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
798798
self_ty: Ty<'tcx>,
799799
trait_segment: &hir::PathSegment<'_>,
800800
is_impl: bool,
801-
constness: Option<ty::BoundConstness>,
801+
constness: ty::BoundConstness,
802802
) -> ty::TraitRef<'tcx> {
803803
let (substs, _) = self.create_substs_for_ast_trait_ref(
804804
span,
@@ -822,7 +822,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
822822
self_ty: Ty<'tcx>,
823823
trait_segment: &'a hir::PathSegment<'a>,
824824
is_impl: bool,
825-
constness: Option<ty::BoundConstness>,
825+
constness: ty::BoundConstness,
826826
) -> (SubstsRef<'tcx>, GenericArgCountResult) {
827827
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
828828

@@ -2129,7 +2129,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
21292129
self_ty,
21302130
trait_segment,
21312131
false,
2132-
Some(constness),
2132+
constness,
21332133
);
21342134

21352135
let item_substs = self.create_substs_for_associated_item(
@@ -2700,7 +2700,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
27002700
&GenericArgs::none(),
27012701
true,
27022702
None,
2703-
None,
2703+
ty::BoundConstness::NotConst,
27042704
);
27052705
EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id)))
27062706
.subst(tcx, substs)

‎compiler/rustc_resolve/src/late/diagnostics.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
322322
}
323323

324324
self.suggest_bare_struct_literal(&mut err);
325-
self.suggest_pattern_match_with_let(&mut err, source, span);
325+
326+
if self.suggest_pattern_match_with_let(&mut err, source, span) {
327+
// Fallback label.
328+
err.span_label(base_error.span, &base_error.fallback_label);
329+
return (err, Vec::new());
330+
}
326331

327332
self.suggest_self_or_self_ref(&mut err, path, span);
328333
self.detect_assoct_type_constraint_meant_as_path(&mut err, &base_error);
@@ -341,7 +346,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
341346
if !self.type_ascription_suggestion(&mut err, base_error.span) {
342347
let mut fallback =
343348
self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error);
349+
350+
// if we have suggested using pattern matching, then don't add needless suggestions
351+
// for typos.
344352
fallback |= self.suggest_typo(&mut err, source, path, span, &base_error);
353+
345354
if fallback {
346355
// Fallback label.
347356
err.span_label(base_error.span, &base_error.fallback_label);
@@ -937,7 +946,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
937946
err: &mut Diagnostic,
938947
source: PathSource<'_>,
939948
span: Span,
940-
) {
949+
) -> bool {
941950
if let PathSource::Expr(_) = source &&
942951
let Some(Expr {
943952
span: expr_span,
@@ -954,8 +963,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
954963
"let ",
955964
Applicability::MaybeIncorrect,
956965
);
966+
return true;
957967
}
958968
}
969+
false
959970
}
960971

961972
fn get_single_associated_item(

‎src/bootstrap/builder.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2207,6 +2207,24 @@ impl<'a> Builder<'a> {
22072207

22082208
false
22092209
}
2210+
2211+
pub(crate) fn maybe_open_in_browser<S: Step>(&self, path: impl AsRef<Path>) {
2212+
if self.was_invoked_explicitly::<S>(Kind::Doc) {
2213+
self.open_in_browser(path);
2214+
}
2215+
}
2216+
2217+
pub(crate) fn open_in_browser(&self, path: impl AsRef<Path>) {
2218+
if self.config.dry_run || !self.config.cmd.open() {
2219+
return;
2220+
}
2221+
2222+
let path = path.as_ref();
2223+
self.info(&format!("Opening doc {}", path.display()));
2224+
if let Err(err) = opener::open(path) {
2225+
self.info(&format!("{}\n", err));
2226+
}
2227+
}
22102228
}
22112229

22122230
#[cfg(test)]

‎src/bootstrap/doc.rs

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -85,18 +85,6 @@ book!(
8585
StyleGuide, "src/doc/style-guide", "style-guide";
8686
);
8787

88-
fn open(builder: &Builder<'_>, path: impl AsRef<Path>) {
89-
if builder.config.dry_run || !builder.config.cmd.open() {
90-
return;
91-
}
92-
93-
let path = path.as_ref();
94-
builder.info(&format!("Opening doc {}", path.display()));
95-
if let Err(err) = opener::open(path) {
96-
builder.info(&format!("{}\n", err));
97-
}
98-
}
99-
10088
// "library/std" -> ["library", "std"]
10189
//
10290
// Used for deciding whether a particular step is one requested by the user on
@@ -240,11 +228,9 @@ impl Step for TheBook {
240228
invoke_rustdoc(builder, compiler, &shared_assets, target, path);
241229
}
242230

243-
if builder.was_invoked_explicitly::<Self>(Kind::Doc) {
244-
let out = builder.doc_out(target);
245-
let index = out.join("book").join("index.html");
246-
open(builder, &index);
247-
}
231+
let out = builder.doc_out(target);
232+
let index = out.join("book").join("index.html");
233+
builder.maybe_open_in_browser::<Self>(index);
248234
}
249235
}
250236

@@ -386,7 +372,7 @@ impl Step for Standalone {
386372
// with no particular explicit doc requested (e.g. library/core).
387373
if builder.paths.is_empty() || builder.was_invoked_explicitly::<Self>(Kind::Doc) {
388374
let index = out.join("index.html");
389-
open(builder, &index);
375+
builder.open_in_browser(&index);
390376
}
391377
}
392378
}
@@ -507,7 +493,7 @@ impl Step for Std {
507493
for requested_crate in requested_crates {
508494
if STD_PUBLIC_CRATES.iter().any(|k| *k == requested_crate.as_str()) {
509495
let index = out.join(requested_crate).join("index.html");
510-
open(builder, &index);
496+
builder.open_in_browser(index);
511497
}
512498
}
513499
}
@@ -759,7 +745,7 @@ impl Step for Rustc {
759745
// Let's open the first crate documentation page:
760746
if let Some(krate) = to_open {
761747
let index = out.join(krate).join("index.html");
762-
open(builder, &index);
748+
builder.open_in_browser(index);
763749
}
764750
}
765751
}
@@ -1019,10 +1005,9 @@ impl Step for RustcBook {
10191005
name: INTERNER.intern_str("rustc"),
10201006
src: INTERNER.intern_path(out_base),
10211007
});
1022-
if builder.was_invoked_explicitly::<Self>(Kind::Doc) {
1023-
let out = builder.doc_out(self.target);
1024-
let index = out.join("rustc").join("index.html");
1025-
open(builder, &index);
1026-
}
1008+
1009+
let out = builder.doc_out(self.target);
1010+
let index = out.join("rustc").join("index.html");
1011+
builder.maybe_open_in_browser::<Self>(index);
10271012
}
10281013
}

‎src/librustdoc/config.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,6 @@ pub(crate) struct RenderOptions {
239239
pub(crate) default_settings: FxHashMap<String, String>,
240240
/// If present, suffix added to CSS/JavaScript files when referencing them in generated pages.
241241
pub(crate) resource_suffix: String,
242-
/// Whether to run the static CSS/JavaScript through a minifier when outputting them. `true` by
243-
/// default.
244-
pub(crate) enable_minification: bool,
245242
/// Whether to create an index page in the root of the output directory. If this is true but
246243
/// `enable_index_page` is None, generate a static listing of crates instead.
247244
pub(crate) enable_index_page: bool,
@@ -416,7 +413,9 @@ impl Options {
416413

417414
let to_check = matches.opt_strs("check-theme");
418415
if !to_check.is_empty() {
419-
let paths = match theme::load_css_paths(static_files::themes::LIGHT) {
416+
let paths = match theme::load_css_paths(
417+
std::str::from_utf8(static_files::STATIC_FILES.theme_light_css.bytes).unwrap(),
418+
) {
420419
Ok(p) => p,
421420
Err(e) => {
422421
diag.struct_err(&e.to_string()).emit();
@@ -557,7 +556,9 @@ impl Options {
557556

558557
let mut themes = Vec::new();
559558
if matches.opt_present("theme") {
560-
let paths = match theme::load_css_paths(static_files::themes::LIGHT) {
559+
let paths = match theme::load_css_paths(
560+
std::str::from_utf8(static_files::STATIC_FILES.theme_light_css.bytes).unwrap(),
561+
) {
561562
Ok(p) => p,
562563
Err(e) => {
563564
diag.struct_err(&e.to_string()).emit();
@@ -675,7 +676,6 @@ impl Options {
675676
ModuleSorting::Alphabetical
676677
};
677678
let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default();
678-
let enable_minification = !matches.opt_present("disable-minification");
679679
let markdown_no_toc = matches.opt_present("markdown-no-toc");
680680
let markdown_css = matches.opt_strs("markdown-css");
681681
let markdown_playground_url = matches.opt_str("markdown-playground-url");
@@ -768,7 +768,6 @@ impl Options {
768768
extern_html_root_takes_precedence,
769769
default_settings,
770770
resource_suffix,
771-
enable_minification,
772771
enable_index_page,
773772
index_page,
774773
static_root_path,

‎src/librustdoc/html/layout.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ use std::path::PathBuf;
22

33
use rustc_data_structures::fx::FxHashMap;
44

5-
use crate::error::Error;
65
use crate::externalfiles::ExternalHtml;
76
use crate::html::format::{Buffer, Print};
87
use crate::html::render::{ensure_trailing_slash, StylePath};
98

109
use askama::Template;
1110

11+
use super::static_files::{StaticFiles, STATIC_FILES};
12+
1213
#[derive(Clone)]
1314
pub(crate) struct Layout {
1415
pub(crate) logo: String,
@@ -34,17 +35,23 @@ pub(crate) struct Page<'a> {
3435
}
3536

3637
impl<'a> Page<'a> {
37-
pub(crate) fn get_static_root_path(&self) -> &str {
38-
self.static_root_path.unwrap_or(self.root_path)
38+
pub(crate) fn get_static_root_path(&self) -> String {
39+
match self.static_root_path {
40+
Some(s) => s.to_string(),
41+
None => format!("{}static.files/", self.root_path),
42+
}
3943
}
4044
}
4145

4246
#[derive(Template)]
4347
#[template(path = "page.html")]
4448
struct PageLayout<'a> {
45-
static_root_path: &'a str,
49+
static_root_path: String,
4650
page: &'a Page<'a>,
4751
layout: &'a Layout,
52+
53+
files: &'static StaticFiles,
54+
4855
themes: Vec<String>,
4956
sidebar: String,
5057
content: String,
@@ -61,19 +68,17 @@ pub(crate) fn render<T: Print, S: Print>(
6168
) -> String {
6269
let static_root_path = page.get_static_root_path();
6370
let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string();
64-
let mut themes: Vec<String> = style_files
65-
.iter()
66-
.map(StylePath::basename)
67-
.collect::<Result<_, Error>>()
68-
.unwrap_or_default();
71+
let mut themes: Vec<String> = style_files.iter().map(|s| s.basename().unwrap()).collect();
6972
themes.sort();
73+
7074
let rustdoc_version = rustc_interface::util::version_str().unwrap_or("unknown version");
7175
let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
7276
let sidebar = Buffer::html().to_display(sidebar);
7377
PageLayout {
7478
static_root_path,
7579
page,
7680
layout,
81+
files: &STATIC_FILES,
7782
themes,
7883
sidebar,
7984
content,

‎src/librustdoc/html/render/context.rs

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use crate::html::escape::Escape;
3232
use crate::html::format::{join_with_double_colon, Buffer};
3333
use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
3434
use crate::html::url_parts_builder::UrlPartsBuilder;
35-
use crate::html::{layout, sources};
35+
use crate::html::{layout, sources, static_files};
3636
use crate::scrape_examples::AllCallLocations;
3737
use crate::try_err;
3838

@@ -498,7 +498,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
498498
);
499499

500500
let (sender, receiver) = channel();
501-
let mut scx = SharedContext {
501+
let scx = SharedContext {
502502
tcx,
503503
src_root,
504504
local_sources,
@@ -521,19 +521,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
521521
call_locations,
522522
};
523523

524-
// Add the default themes to the `Vec` of stylepaths
525-
//
526-
// Note that these must be added before `sources::render` is called
527-
// so that the resulting source pages are styled
528-
//
529-
// `light.css` is not disabled because it is the stylesheet that stays loaded
530-
// by the browser as the theme stylesheet. The theme system (hackily) works by
531-
// changing the href to this stylesheet. All other themes are disabled to
532-
// prevent rule conflicts
533-
scx.style_files.push(StylePath { path: PathBuf::from("light.css") });
534-
scx.style_files.push(StylePath { path: PathBuf::from("dark.css") });
535-
scx.style_files.push(StylePath { path: PathBuf::from("ayu.css") });
536-
537524
let dst = output;
538525
scx.ensure_dir(&dst)?;
539526

@@ -647,10 +634,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
647634
</section>\
648635
</noscript>\
649636
<link rel=\"stylesheet\" type=\"text/css\" \
650-
href=\"{root_path}settings{suffix}.css\">\
651-
<script defer src=\"{root_path}settings{suffix}.js\"></script>",
652-
root_path = page.static_root_path.unwrap_or(""),
653-
suffix = page.resource_suffix,
637+
href=\"{static_root_path}{settings_css}\">\
638+
<script defer src=\"{static_root_path}{settings_js}\"></script>",
639+
static_root_path = page.get_static_root_path(),
640+
settings_css = static_files::STATIC_FILES.settings_css,
641+
settings_js = static_files::STATIC_FILES.settings_js,
654642
)
655643
},
656644
&shared.style_files,

‎src/librustdoc/html/render/print_item.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ use crate::html::format::{
3030
join_with_double_colon, print_abi_with_space, print_constness_with_space, print_where_clause,
3131
visibility_print_with_space, Buffer, Ending, PrintWithSpace,
3232
};
33-
use crate::html::highlight;
3433
use crate::html::layout::Page;
3534
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
3635
use crate::html::url_parts_builder::UrlPartsBuilder;
36+
use crate::html::{highlight, static_files};
3737

3838
use askama::Template;
3939
use itertools::Itertools;
@@ -52,8 +52,8 @@ struct PathComponent {
5252
#[derive(Template)]
5353
#[template(path = "print_item.html")]
5454
struct ItemVars<'a> {
55-
page: &'a Page<'a>,
5655
static_root_path: &'a str,
56+
clipboard_svg: &'static static_files::StaticFile,
5757
typ: &'a str,
5858
name: &'a str,
5959
item_type: &'a str,
@@ -147,8 +147,8 @@ pub(super) fn print_item(
147147
};
148148

149149
let item_vars = ItemVars {
150-
page,
151-
static_root_path: page.get_static_root_path(),
150+
static_root_path: &page.get_static_root_path(),
151+
clipboard_svg: &static_files::STATIC_FILES.clipboard_svg,
152152
typ,
153153
name: item.name.as_ref().unwrap().as_str(),
154154
item_type: &item.type_().to_string(),

‎src/librustdoc/html/render/write_shared.rs

Lines changed: 49 additions & 241 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
use std::ffi::OsStr;
21
use std::fs::{self, File};
32
use std::io::prelude::*;
43
use std::io::{self, BufReader};
5-
use std::path::{Component, Path, PathBuf};
4+
use std::path::{Component, Path};
65
use std::rc::Rc;
7-
use std::sync::LazyLock as Lazy;
86

97
use itertools::Itertools;
108
use rustc_data_structures::flock;
@@ -20,123 +18,20 @@ use crate::error::Error;
2018
use crate::html::{layout, static_files};
2119
use crate::{try_err, try_none};
2220

23-
static FILES_UNVERSIONED: Lazy<FxHashMap<&str, &[u8]>> = Lazy::new(|| {
24-
map! {
25-
"FiraSans-Regular.woff2" => static_files::fira_sans::REGULAR,
26-
"FiraSans-Medium.woff2" => static_files::fira_sans::MEDIUM,
27-
"FiraSans-LICENSE.txt" => static_files::fira_sans::LICENSE,
28-
"SourceSerif4-Regular.ttf.woff2" => static_files::source_serif_4::REGULAR,
29-
"SourceSerif4-Bold.ttf.woff2" => static_files::source_serif_4::BOLD,
30-
"SourceSerif4-It.ttf.woff2" => static_files::source_serif_4::ITALIC,
31-
"SourceSerif4-LICENSE.md" => static_files::source_serif_4::LICENSE,
32-
"SourceCodePro-Regular.ttf.woff2" => static_files::source_code_pro::REGULAR,
33-
"SourceCodePro-Semibold.ttf.woff2" => static_files::source_code_pro::SEMIBOLD,
34-
"SourceCodePro-It.ttf.woff2" => static_files::source_code_pro::ITALIC,
35-
"SourceCodePro-LICENSE.txt" => static_files::source_code_pro::LICENSE,
36-
"NanumBarunGothic.ttf.woff2" => static_files::nanum_barun_gothic::REGULAR,
37-
"NanumBarunGothic-LICENSE.txt" => static_files::nanum_barun_gothic::LICENSE,
38-
"LICENSE-MIT.txt" => static_files::LICENSE_MIT,
39-
"LICENSE-APACHE.txt" => static_files::LICENSE_APACHE,
40-
"COPYRIGHT.txt" => static_files::COPYRIGHT,
41-
}
42-
});
43-
44-
enum SharedResource<'a> {
45-
/// This file will never change, no matter what toolchain is used to build it.
46-
///
47-
/// It does not have a resource suffix.
48-
Unversioned { name: &'static str },
49-
/// This file may change depending on the toolchain.
50-
///
51-
/// It has a resource suffix.
52-
ToolchainSpecific { basename: &'static str },
53-
/// This file may change for any crate within a build, or based on the CLI arguments.
54-
///
55-
/// This differs from normal invocation-specific files because it has a resource suffix.
56-
InvocationSpecific { basename: &'a str },
57-
}
58-
59-
impl SharedResource<'_> {
60-
fn extension(&self) -> Option<&OsStr> {
61-
use SharedResource::*;
62-
match self {
63-
Unversioned { name }
64-
| ToolchainSpecific { basename: name }
65-
| InvocationSpecific { basename: name } => Path::new(name).extension(),
66-
}
67-
}
68-
69-
fn path(&self, cx: &Context<'_>) -> PathBuf {
70-
match self {
71-
SharedResource::Unversioned { name } => cx.dst.join(name),
72-
SharedResource::ToolchainSpecific { basename } => cx.suffix_path(basename),
73-
SharedResource::InvocationSpecific { basename } => cx.suffix_path(basename),
74-
}
75-
}
76-
77-
fn should_emit(&self, emit: &[EmitType]) -> bool {
78-
if emit.is_empty() {
79-
return true;
80-
}
81-
let kind = match self {
82-
SharedResource::Unversioned { .. } => EmitType::Unversioned,
83-
SharedResource::ToolchainSpecific { .. } => EmitType::Toolchain,
84-
SharedResource::InvocationSpecific { .. } => EmitType::InvocationSpecific,
85-
};
86-
emit.contains(&kind)
87-
}
88-
}
89-
90-
impl Context<'_> {
91-
fn suffix_path(&self, filename: &str) -> PathBuf {
92-
// We use splitn vs Path::extension here because we might get a filename
93-
// like `style.min.css` and we want to process that into
94-
// `style-suffix.min.css`. Path::extension would just return `css`
95-
// which would result in `style.min-suffix.css` which isn't what we
96-
// want.
97-
let (base, ext) = filename.split_once('.').unwrap();
98-
let filename = format!("{}{}.{}", base, self.shared.resource_suffix, ext);
99-
self.dst.join(&filename)
100-
}
101-
102-
fn write_shared(
103-
&self,
104-
resource: SharedResource<'_>,
105-
contents: impl 'static + Send + AsRef<[u8]>,
106-
emit: &[EmitType],
107-
) -> Result<(), Error> {
108-
if resource.should_emit(emit) {
109-
self.shared.fs.write(resource.path(self), contents)
110-
} else {
111-
Ok(())
112-
}
113-
}
114-
115-
fn write_minify(
116-
&self,
117-
resource: SharedResource<'_>,
118-
contents: impl 'static + Send + AsRef<str> + AsRef<[u8]>,
119-
minify: bool,
120-
emit: &[EmitType],
121-
) -> Result<(), Error> {
122-
if minify {
123-
let contents = contents.as_ref();
124-
let contents = if resource.extension() == Some(OsStr::new("css")) {
125-
minifier::css::minify(contents)
126-
.map_err(|e| {
127-
Error::new(format!("failed to minify CSS file: {}", e), resource.path(self))
128-
})?
129-
.to_string()
130-
} else {
131-
minifier::js::minify(contents).to_string()
132-
};
133-
self.write_shared(resource, contents, emit)
134-
} else {
135-
self.write_shared(resource, contents, emit)
136-
}
137-
}
138-
}
139-
21+
/// Rustdoc writes out two kinds of shared files:
22+
/// - Static files, which are embedded in the rustdoc binary and are written with a
23+
/// filename that includes a hash of their contents. These will always have a new
24+
/// URL if the contents change, so they are safe to cache with the
25+
/// `Cache-Control: immutable` directive. They are written under the static.files/
26+
/// directory and are written when --emit-type is empty (default) or contains
27+
/// "toolchain-specific". If using the --static-root-path flag, it should point
28+
/// to a URL path prefix where each of these filenames can be fetched.
29+
/// - Invocation specific files. These are generated based on the crate(s) being
30+
/// documented. Their filenames need to be predictable without knowing their
31+
/// contents, so they do not include a hash in their filename and are not safe to
32+
/// cache with `Cache-Control: immutable`. They include the contents of the
33+
/// --resource-suffix flag and are emitted when --emit-type is empty (default)
34+
/// or contains "invocation-specific".
14035
pub(super) fn write_shared(
14136
cx: &mut Context<'_>,
14237
krate: &Crate,
@@ -149,139 +44,52 @@ pub(super) fn write_shared(
14944
let lock_file = cx.dst.join(".lock");
15045
let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file);
15146

152-
// Minified resources are usually toolchain resources. If they're not, they should use `cx.write_minify` directly.
153-
fn write_minify(
154-
basename: &'static str,
155-
contents: impl 'static + Send + AsRef<str> + AsRef<[u8]>,
156-
cx: &Context<'_>,
157-
options: &RenderOptions,
158-
) -> Result<(), Error> {
159-
cx.write_minify(
160-
SharedResource::ToolchainSpecific { basename },
161-
contents,
162-
options.enable_minification,
163-
&options.emit,
164-
)
165-
}
166-
167-
// Toolchain resources should never be dynamic.
168-
let write_toolchain = |p: &'static _, c: &'static _| {
169-
cx.write_shared(SharedResource::ToolchainSpecific { basename: p }, c, &options.emit)
170-
};
171-
172-
// Crate resources should always be dynamic.
173-
let write_crate = |p: &_, make_content: &dyn Fn() -> Result<Vec<u8>, Error>| {
47+
// InvocationSpecific resources should always be dynamic.
48+
let write_invocation_specific = |p: &str, make_content: &dyn Fn() -> Result<Vec<u8>, Error>| {
17449
let content = make_content()?;
175-
cx.write_shared(SharedResource::InvocationSpecific { basename: p }, content, &options.emit)
50+
if options.emit.is_empty() || options.emit.contains(&EmitType::InvocationSpecific) {
51+
let output_filename = static_files::suffix_path(p, &cx.shared.resource_suffix);
52+
cx.shared.fs.write(cx.dst.join(output_filename), content)
53+
} else {
54+
Ok(())
55+
}
17656
};
17757

178-
// Given "foo.svg", return e.g. "url(\"foo1.58.0.svg\")"
179-
fn ver_url(cx: &Context<'_>, basename: &'static str) -> String {
180-
format!(
181-
"url(\"{}\")",
182-
SharedResource::ToolchainSpecific { basename }
183-
.path(cx)
184-
.file_name()
185-
.unwrap()
186-
.to_str()
187-
.unwrap()
188-
)
189-
}
190-
191-
// We use the AUTOREPLACE mechanism to inject into our static JS and CSS certain
192-
// values that are only known at doc build time. Since this mechanism is somewhat
193-
// surprising when reading the code, please limit it to rustdoc.css.
194-
write_minify(
195-
"rustdoc.css",
196-
static_files::RUSTDOC_CSS
197-
.replace(
198-
"/* AUTOREPLACE: */url(\"toggle-minus.svg\")",
199-
&ver_url(cx, "toggle-minus.svg"),
200-
)
201-
.replace("/* AUTOREPLACE: */url(\"toggle-plus.svg\")", &ver_url(cx, "toggle-plus.svg"))
202-
.replace("/* AUTOREPLACE: */url(\"down-arrow.svg\")", &ver_url(cx, "down-arrow.svg")),
203-
cx,
204-
options,
205-
)?;
206-
207-
// Add all the static files. These may already exist, but we just
208-
// overwrite them anyway to make sure that they're fresh and up-to-date.
209-
write_minify("settings.css", static_files::SETTINGS_CSS, cx, options)?;
210-
write_minify("noscript.css", static_files::NOSCRIPT_CSS, cx, options)?;
211-
212-
// To avoid "light.css" to be overwritten, we'll first run over the received themes and only
213-
// then we'll run over the "official" styles.
214-
let mut themes: FxHashSet<String> = FxHashSet::default();
58+
cx.shared
59+
.fs
60+
.create_dir_all(cx.dst.join("static.files"))
61+
.map_err(|e| PathError::new(e, "static.files"))?;
21562

63+
// Handle added third-party themes
21664
for entry in &cx.shared.style_files {
21765
let theme = entry.basename()?;
21866
let extension =
21967
try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path);
22068

221-
// Handle the official themes
222-
match theme.as_str() {
223-
"light" => write_minify("light.css", static_files::themes::LIGHT, cx, options)?,
224-
"dark" => write_minify("dark.css", static_files::themes::DARK, cx, options)?,
225-
"ayu" => write_minify("ayu.css", static_files::themes::AYU, cx, options)?,
226-
_ => {
227-
// Handle added third-party themes
228-
let filename = format!("{}.{}", theme, extension);
229-
write_crate(&filename, &|| Ok(try_err!(fs::read(&entry.path), &entry.path)))?;
230-
}
231-
};
232-
233-
themes.insert(theme.to_owned());
234-
}
235-
236-
if (*cx.shared).layout.logo.is_empty() {
237-
write_toolchain("rust-logo.svg", static_files::RUST_LOGO_SVG)?;
238-
}
239-
if (*cx.shared).layout.favicon.is_empty() {
240-
write_toolchain("favicon.svg", static_files::RUST_FAVICON_SVG)?;
241-
write_toolchain("favicon-16x16.png", static_files::RUST_FAVICON_PNG_16)?;
242-
write_toolchain("favicon-32x32.png", static_files::RUST_FAVICON_PNG_32)?;
243-
}
244-
write_toolchain("wheel.svg", static_files::WHEEL_SVG)?;
245-
write_toolchain("clipboard.svg", static_files::CLIPBOARD_SVG)?;
246-
write_toolchain("down-arrow.svg", static_files::DOWN_ARROW_SVG)?;
247-
write_toolchain("toggle-minus.svg", static_files::TOGGLE_MINUS_PNG)?;
248-
write_toolchain("toggle-plus.svg", static_files::TOGGLE_PLUS_PNG)?;
249-
250-
let mut themes: Vec<&String> = themes.iter().collect();
251-
themes.sort();
252-
253-
write_minify("main.js", static_files::MAIN_JS, cx, options)?;
254-
write_minify("search.js", static_files::SEARCH_JS, cx, options)?;
255-
write_minify("settings.js", static_files::SETTINGS_JS, cx, options)?;
256-
257-
if cx.include_sources {
258-
write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT, cx, options)?;
259-
}
260-
261-
write_minify("storage.js", static_files::STORAGE_JS, cx, options)?;
69+
// Skip the official themes. They are written below as part of STATIC_FILES_LIST.
70+
if matches!(theme.as_str(), "light" | "dark" | "ayu") {
71+
continue;
72+
}
26273

263-
if cx.shared.layout.scrape_examples_extension {
264-
cx.write_minify(
265-
SharedResource::InvocationSpecific { basename: "scrape-examples.js" },
266-
static_files::SCRAPE_EXAMPLES_JS,
267-
options.enable_minification,
268-
&options.emit,
269-
)?;
74+
let bytes = try_err!(fs::read(&entry.path), &entry.path);
75+
let filename = format!("{}{}.{}", theme, cx.shared.resource_suffix, extension);
76+
cx.shared.fs.write(cx.dst.join(filename), bytes)?;
27077
}
27178

79+
// When the user adds their own CSS files with --extend-css, we write that as an
80+
// invocation-specific file (that is, with a resource suffix).
27281
if let Some(ref css) = cx.shared.layout.css_file_extension {
27382
let buffer = try_err!(fs::read_to_string(css), css);
274-
// This varies based on the invocation, so it can't go through the write_minify wrapper.
275-
cx.write_minify(
276-
SharedResource::InvocationSpecific { basename: "theme.css" },
277-
buffer,
278-
options.enable_minification,
279-
&options.emit,
280-
)?;
83+
let path = static_files::suffix_path("theme.css", &cx.shared.resource_suffix);
84+
cx.shared.fs.write(cx.dst.join(path), buffer)?;
28185
}
282-
write_minify("normalize.css", static_files::NORMALIZE_CSS, cx, options)?;
283-
for (name, contents) in &*FILES_UNVERSIONED {
284-
cx.write_shared(SharedResource::Unversioned { name }, contents, &options.emit)?;
86+
87+
if options.emit.is_empty() || options.emit.contains(&EmitType::Toolchain) {
88+
let static_dir = cx.dst.join(Path::new("static.files"));
89+
static_files::for_each(|f: &static_files::StaticFile| {
90+
let filename = static_dir.join(f.output_filename());
91+
cx.shared.fs.write(filename, f.minified())
92+
})?;
28593
}
28694

28795
/// Read a file and return all lines that match the `"{crate}":{data},` format,
@@ -463,7 +271,7 @@ pub(super) fn write_shared(
463271
v.push_str("\\\n}');\ncreateSourceSidebar();\n");
464272
Ok(v.into_bytes())
465273
};
466-
write_crate("source-files.js", &make_sources)?;
274+
write_invocation_specific("source-files.js", &make_sources)?;
467275
}
468276

469277
// Update the search index and crate list.
@@ -477,7 +285,7 @@ pub(super) fn write_shared(
477285
// Sort the indexes by crate so the file will be generated identically even
478286
// with rustdoc running in parallel.
479287
all_indexes.sort();
480-
write_crate("search-index.js", &|| {
288+
write_invocation_specific("search-index.js", &|| {
481289
let mut v = String::from("var searchIndex = JSON.parse('{\\\n");
482290
v.push_str(&all_indexes.join(",\\\n"));
483291
v.push_str(
@@ -490,7 +298,7 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
490298
Ok(v.into_bytes())
491299
})?;
492300

493-
write_crate("crates.js", &|| {
301+
write_invocation_specific("crates.js", &|| {
494302
let krates = krates.iter().map(|k| format!("\"{}\"", k)).join(",");
495303
Ok(format!("window.ALL_CRATES = [{}];", krates).into_bytes())
496304
})?;

‎src/librustdoc/html/static/css/rustdoc.css

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
font-style: normal;
55
font-weight: 400;
66
src: local('Fira Sans'),
7-
url("FiraSans-Regular.woff2") format("woff2");
7+
url("FiraSans-Regular-018c141bf0843ffd.woff2") format("woff2");
88
font-display: swap;
99
}
1010
@font-face {
1111
font-family: 'Fira Sans';
1212
font-style: normal;
1313
font-weight: 500;
1414
src: local('Fira Sans Medium'),
15-
url("FiraSans-Medium.woff2") format("woff2");
15+
url("FiraSans-Medium-8f9a781e4970d388.woff2") format("woff2");
1616
font-display: swap;
1717
}
1818

@@ -22,23 +22,23 @@
2222
font-style: normal;
2323
font-weight: 400;
2424
src: local('Source Serif 4'),
25-
url("SourceSerif4-Regular.ttf.woff2") format("woff2");
25+
url("SourceSerif4-Regular-1f7d512b176f0f72.ttf.woff2") format("woff2");
2626
font-display: swap;
2727
}
2828
@font-face {
2929
font-family: 'Source Serif 4';
3030
font-style: italic;
3131
font-weight: 400;
3232
src: local('Source Serif 4 Italic'),
33-
url("SourceSerif4-It.ttf.woff2") format("woff2");
33+
url("SourceSerif4-It-d034fe4ef9d0fa00.ttf.woff2") format("woff2");
3434
font-display: swap;
3535
}
3636
@font-face {
3737
font-family: 'Source Serif 4';
3838
font-style: normal;
3939
font-weight: 700;
4040
src: local('Source Serif 4 Bold'),
41-
url("SourceSerif4-Bold.ttf.woff2") format("woff2");
41+
url("SourceSerif4-Bold-124a1ca42af929b6.ttf.woff2") format("woff2");
4242
font-display: swap;
4343
}
4444

@@ -49,28 +49,28 @@
4949
font-weight: 400;
5050
/* Avoid using locally installed font because bad versions are in circulation:
5151
* see https://github.com/rust-lang/rust/issues/24355 */
52-
src: url("SourceCodePro-Regular.ttf.woff2") format("woff2");
52+
src: url("SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2") format("woff2");
5353
font-display: swap;
5454
}
5555
@font-face {
5656
font-family: 'Source Code Pro';
5757
font-style: italic;
5858
font-weight: 400;
59-
src: url("SourceCodePro-It.ttf.woff2") format("woff2");
59+
src: url("SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2") format("woff2");
6060
font-display: swap;
6161
}
6262
@font-face {
6363
font-family: 'Source Code Pro';
6464
font-style: normal;
6565
font-weight: 600;
66-
src: url("SourceCodePro-Semibold.ttf.woff2") format("woff2");
66+
src: url("SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2") format("woff2");
6767
font-display: swap;
6868
}
6969

7070
/* Avoid using legacy CJK serif fonts in Windows like Batang. */
7171
@font-face {
7272
font-family: 'NanumBarunGothic';
73-
src: url("NanumBarunGothic.ttf.woff2") format("woff2");
73+
src: url("NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2") format("woff2");
7474
font-display: swap;
7575
unicode-range: U+AC00-D7AF, U+1100-11FF, U+3130-318F, U+A960-A97F, U+D7B0-D7FF;
7676
}
@@ -850,7 +850,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
850850
background-size: 20px;
851851
background-position: calc(100% - 2px) 56%;
852852
/* image is black color, themes should apply a "filter" property to change the color */
853-
background-image: /* AUTOREPLACE: */url("down-arrow.svg");
853+
background-image: url("down-arrow-2d685a4bae708e15.svg");
854854
}
855855
#crate-search > option {
856856
font-size: 1rem;
@@ -886,7 +886,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
886886
/* A little margin ensures the browser's outlining of focused links has room to display. */
887887
margin-left: 2px;
888888
margin-right: 2px;
889-
border-bottom: 1px solid var(--border-color);
889+
border-bottom: 1px solid var(--search-result-border-color);
890890
gap: 1em;
891891
}
892892

@@ -1617,11 +1617,11 @@ details.rustdoc-toggle[open] > summary.hideme > span {
16171617

16181618
details.rustdoc-toggle[open] > summary::before,
16191619
details.rustdoc-toggle[open] > summary.hideme::before {
1620-
background-image: /* AUTOREPLACE: */url("toggle-minus.svg");
1620+
background-image: url("toggle-minus-31bbd6e4c77f5c96.svg");
16211621
}
16221622

16231623
details.rustdoc-toggle > summary::before {
1624-
background-image: /* AUTOREPLACE: */url("toggle-plus.svg");
1624+
background-image: url("toggle-plus-1092eb4930d581b0.svg");
16251625
}
16261626

16271627
details.rustdoc-toggle[open] > summary::before,

‎src/librustdoc/html/static/css/themes/ayu.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
3838
--sidebar-link-color: #53b1db;
3939
--sidebar-current-link-background-color: transparent;
4040
--search-result-link-focus-background-color: #3c3c3c;
41+
--search-result-border-color: #aaa3;
4142
--stab-background-color: #314559;
4243
--stab-code-color: #e6e1cf;
4344
--search-color: #fff;

‎src/librustdoc/html/static/css/themes/dark.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
--sidebar-link-color: #fdbf35;
3434
--sidebar-current-link-background-color: #444;
3535
--search-result-link-focus-background-color: #616161;
36+
--search-result-border-color: #aaa3;
3637
--stab-background-color: #314559;
3738
--stab-code-color: #e6e1cf;
3839
--search-color: #111;

‎src/librustdoc/html/static/css/themes/light.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
--sidebar-link-color: #356da4;
3434
--sidebar-current-link-background-color: #fff;
3535
--search-result-link-focus-background-color: #ccc;
36+
--search-result-border-color: #aaa3;
3637
--stab-background-color: #fff5d6;
3738
--stab-code-color: #000;
3839
--search-color: #000;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
The Nanum Barun Gothic fonts are shipped with rustdoc because the default fonts
2+
on many Windows installs render Korean very badly. See:
3+
- https://github.com/rust-lang/rust/pull/84048,
4+
- https://github.com/rust-lang/rust/issues/84035
5+
- https://github.com/rust-lang/rust/pull/90232
6+
7+
The font files were generated with these commands:
8+
9+
```sh
10+
pyftsubset NanumBarunGothic.ttf \
11+
--unicodes=U+AC00-D7AF:U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF \
12+
--output-file=NanumBarunGothic.ttf.woff2 --flavor=woff2

‎src/librustdoc/html/static/js/main.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,9 @@ function browserSupportsHistoryApi() {
183183
}
184184

185185
// eslint-disable-next-line no-unused-vars
186-
function loadCss(cssFileName) {
186+
function loadCss(cssUrl) {
187187
const link = document.createElement("link");
188-
link.href = resourcePath(cssFileName, ".css");
188+
link.href = cssUrl;
189189
link.type = "text/css";
190190
link.rel = "stylesheet";
191191
document.getElementsByTagName("head")[0].appendChild(link);
@@ -208,8 +208,8 @@ function loadCss(cssFileName) {
208208
event.preventDefault();
209209
// Sending request for the CSS and the JS files at the same time so it will
210210
// hopefully be loaded when the JS will generate the settings content.
211-
loadCss("settings");
212-
loadScript(resourcePath("settings", ".js"));
211+
loadCss(getVar("static-root-path") + getVar("settings-css"));
212+
loadScript(getVar("static-root-path") + getVar("settings-js"));
213213
};
214214

215215
window.searchState = {
@@ -286,7 +286,7 @@ function loadCss(cssFileName) {
286286
function loadSearch() {
287287
if (!searchLoaded) {
288288
searchLoaded = true;
289-
loadScript(resourcePath("search", ".js"));
289+
loadScript(getVar("static-root-path") + getVar("search-js"));
290290
loadScript(resourcePath("search-index", ".js"));
291291
}
292292
}

‎src/librustdoc/html/static/js/settings.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,9 @@
154154
* @return {HTMLElement}
155155
*/
156156
function buildSettingsPage() {
157-
const themes = getVar("themes").split(",");
157+
const theme_names = getVar("themes").split(",").filter(t => t);
158+
theme_names.push("light", "dark", "ayu");
159+
158160
const settings = [
159161
{
160162
"name": "Use system theme",
@@ -165,19 +167,19 @@
165167
"name": "Theme",
166168
"js_name": "theme",
167169
"default": "light",
168-
"options": themes,
170+
"options": theme_names,
169171
},
170172
{
171173
"name": "Preferred light theme",
172174
"js_name": "preferred-light-theme",
173175
"default": "light",
174-
"options": themes,
176+
"options": theme_names,
175177
},
176178
{
177179
"name": "Preferred dark theme",
178180
"js_name": "preferred-dark-theme",
179181
"default": "dark",
180-
"options": themes,
182+
"options": theme_names,
181183
},
182184
{
183185
"name": "Auto-hide item contents for large items",

‎src/librustdoc/html/static/js/storage.js

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -126,33 +126,29 @@ function getCurrentValue(name) {
126126
}
127127
}
128128

129-
function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
130-
const newHref = mainStyleElem.href.replace(
131-
/\/rustdoc([^/]*)\.css/, "/" + newTheme + "$1" + ".css");
132-
129+
function switchTheme(styleElem, mainStyleElem, newThemeName, saveTheme) {
133130
// If this new value comes from a system setting or from the previously
134131
// saved theme, no need to save it.
135132
if (saveTheme) {
136-
updateLocalStorage("theme", newTheme);
137-
}
138-
139-
if (styleElem.href === newHref) {
140-
return;
133+
updateLocalStorage("theme", newThemeName);
141134
}
142135

143-
let found = false;
144136
if (savedHref.length === 0) {
145137
onEachLazy(document.getElementsByTagName("link"), el => {
146138
savedHref.push(el.href);
147139
});
148140
}
149-
onEach(savedHref, el => {
150-
if (el === newHref) {
151-
found = true;
141+
const newHref = savedHref.find(url => {
142+
const m = url.match(/static\.files\/(.*)-[a-f0-9]{16}\.css$/);
143+
if (m && m[1] === newThemeName) {
144+
return true;
145+
}
146+
const m2 = url.match(/\/([^/]*)\.css$/);
147+
if (m2 && m2[1].startsWith(newThemeName)) {
152148
return true;
153149
}
154150
});
155-
if (found) {
151+
if (newHref && newHref !== styleElem.href) {
156152
styleElem.href = newHref;
157153
}
158154
}

‎src/librustdoc/html/static_files.rs

Lines changed: 110 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -2,167 +2,128 @@
22
//!
33
//! All the static files are included here for centralized access in case anything other than the
44
//! HTML rendering code (say, the theme checker) needs to access one of these files.
5-
//!
6-
//! Note about types: CSS and JavaScript files are included as `&'static str` to allow for the
7-
//! minifier to run on them. All other files are included as `&'static [u8]` so they can be
8-
//! directly written to a `Write` handle.
9-
10-
/// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page.
11-
pub(crate) static RUSTDOC_CSS: &str = include_str!("static/css/rustdoc.css");
12-
13-
/// The file contents of `settings.css`, responsible for the items on the settings page.
14-
pub(crate) static SETTINGS_CSS: &str = include_str!("static/css/settings.css");
15-
16-
/// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled.
17-
pub(crate) static NOSCRIPT_CSS: &str = include_str!("static/css/noscript.css");
18-
19-
/// The file contents of `normalize.css`, included to even out standard elements between browser
20-
/// implementations.
21-
pub(crate) static NORMALIZE_CSS: &str = include_str!("static/css/normalize.css");
22-
23-
/// The file contents of `main.js`, which contains the core JavaScript used on documentation pages,
24-
/// including search behavior and docblock folding, among others.
25-
pub(crate) static MAIN_JS: &str = include_str!("static/js/main.js");
26-
27-
/// The file contents of `search.js`, which contains the search behavior.
28-
pub(crate) static SEARCH_JS: &str = include_str!("static/js/search.js");
29-
30-
/// The file contents of `settings.js`, which contains the JavaScript used to handle the settings
31-
/// page.
32-
pub(crate) static SETTINGS_JS: &str = include_str!("static/js/settings.js");
33-
34-
/// The file contents of `storage.js`, which contains functionality related to browser Local
35-
/// Storage, used to store documentation settings.
36-
pub(crate) static STORAGE_JS: &str = include_str!("static/js/storage.js");
37-
38-
/// The file contents of `scraped-examples.js`, which contains functionality related to the
39-
/// --scrape-examples flag that inserts automatically-found examples of usages of items.
40-
pub(crate) static SCRAPE_EXAMPLES_JS: &str = include_str!("static/js/scrape-examples.js");
41-
42-
pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/scrape-examples-help.md");
43-
44-
/// The file contents of `wheel.svg`, the icon used for the settings button.
45-
pub(crate) static WHEEL_SVG: &[u8] = include_bytes!("static/images/wheel.svg");
46-
47-
/// The file contents of `clipboard.svg`, the icon used for the "copy path" button.
48-
pub(crate) static CLIPBOARD_SVG: &[u8] = include_bytes!("static/images/clipboard.svg");
49-
50-
/// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox.
51-
pub(crate) static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/images/down-arrow.svg");
52-
53-
/// The file contents of `toggle-minus.svg`, the icon used for opened toggles.
54-
pub(crate) static TOGGLE_MINUS_PNG: &[u8] = include_bytes!("static/images/toggle-minus.svg");
55-
56-
/// The file contents of `toggle-plus.svg`, the icon used for closed toggles.
57-
pub(crate) static TOGGLE_PLUS_PNG: &[u8] = include_bytes!("static/images/toggle-plus.svg");
585
59-
/// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation
60-
/// output.
61-
pub(crate) static COPYRIGHT: &[u8] = include_bytes!("static/COPYRIGHT.txt");
6+
use rustc_data_structures::fx::FxHasher;
7+
use std::hash::Hasher;
8+
use std::path::{Path, PathBuf};
9+
use std::{fmt, str};
6210

63-
/// The contents of `LICENSE-APACHE.txt`, the text of the Apache License, version 2.0.
64-
pub(crate) static LICENSE_APACHE: &[u8] = include_bytes!("static/LICENSE-APACHE.txt");
65-
66-
/// The contents of `LICENSE-MIT.txt`, the text of the MIT License.
67-
pub(crate) static LICENSE_MIT: &[u8] = include_bytes!("static/LICENSE-MIT.txt");
68-
69-
/// The contents of `rust-logo.svg`, the default icon of the documentation.
70-
pub(crate) static RUST_LOGO_SVG: &[u8] = include_bytes!("static/images/rust-logo.svg");
71-
72-
/// The default documentation favicons (SVG and PNG fallbacks)
73-
pub(crate) static RUST_FAVICON_SVG: &[u8] = include_bytes!("static/images/favicon.svg");
74-
pub(crate) static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/images/favicon-16x16.png");
75-
pub(crate) static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/images/favicon-32x32.png");
76-
77-
/// The built-in themes given to every documentation site.
78-
pub(crate) mod themes {
79-
/// The "light" theme, selected by default when no setting is available. Used as the basis for
80-
/// the `--check-theme` functionality.
81-
pub(crate) static LIGHT: &str = include_str!("static/css/themes/light.css");
82-
83-
/// The "dark" theme.
84-
pub(crate) static DARK: &str = include_str!("static/css/themes/dark.css");
85-
86-
/// The "ayu" theme.
87-
pub(crate) static AYU: &str = include_str!("static/css/themes/ayu.css");
11+
pub(crate) struct StaticFile {
12+
pub(crate) filename: PathBuf,
13+
pub(crate) bytes: &'static [u8],
8814
}
8915

90-
/// Files related to the Fira Sans font.
91-
pub(crate) mod fira_sans {
92-
/// The file `FiraSans-Regular.woff2`, the Regular variant of the Fira Sans font in woff2.
93-
pub(crate) static REGULAR: &[u8] = include_bytes!("static/fonts/FiraSans-Regular.woff2");
94-
95-
/// The file `FiraSans-Medium.woff2`, the Medium variant of the Fira Sans font in woff2.
96-
pub(crate) static MEDIUM: &[u8] = include_bytes!("static/fonts/FiraSans-Medium.woff2");
97-
98-
/// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font.
99-
pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/FiraSans-LICENSE.txt");
16+
impl StaticFile {
17+
fn new(filename: &str, bytes: &'static [u8]) -> StaticFile {
18+
Self { filename: static_filename(filename, bytes), bytes }
19+
}
20+
21+
pub(crate) fn minified(&self) -> Vec<u8> {
22+
if self.filename.ends_with(".css") {
23+
minifier::css::minify(str::from_utf8(self.bytes).unwrap()).unwrap().to_string().into()
24+
} else if self.filename.ends_with(".js") {
25+
minifier::js::minify(str::from_utf8(self.bytes).unwrap()).to_string().into()
26+
} else {
27+
self.bytes.to_owned()
28+
}
29+
}
30+
31+
pub(crate) fn output_filename(&self) -> &Path {
32+
&self.filename
33+
}
10034
}
10135

102-
/// Files related to the Source Serif 4 font.
103-
pub(crate) mod source_serif_4 {
104-
/// The file `SourceSerif4-Regular.ttf.woff2`, the Regular variant of the Source Serif 4 font in
105-
/// woff2.
106-
pub(crate) static REGULAR: &[u8] =
107-
include_bytes!("static/fonts/SourceSerif4-Regular.ttf.woff2");
108-
109-
/// The file `SourceSerif4-Bold.ttf.woff2`, the Bold variant of the Source Serif 4 font in
110-
/// woff2.
111-
pub(crate) static BOLD: &[u8] = include_bytes!("static/fonts/SourceSerif4-Bold.ttf.woff2");
112-
113-
/// The file `SourceSerif4-It.ttf.woff2`, the Italic variant of the Source Serif 4 font in
114-
/// woff2.
115-
pub(crate) static ITALIC: &[u8] = include_bytes!("static/fonts/SourceSerif4-It.ttf.woff2");
116-
117-
/// The file `SourceSerif4-LICENSE.txt`, the license text for the Source Serif 4 font.
118-
pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/SourceSerif4-LICENSE.md");
36+
/// The Display implementation for a StaticFile outputs its filename. This makes it
37+
/// convenient to interpolate static files into HTML templates.
38+
impl fmt::Display for StaticFile {
39+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40+
write!(f, "{}", self.output_filename().display())
41+
}
11942
}
12043

121-
/// Files related to the Source Code Pro font.
122-
pub(crate) mod source_code_pro {
123-
/// The file `SourceCodePro-Regular.ttf.woff2`, the Regular variant of the Source Code Pro font
124-
/// in woff2.
125-
pub(crate) static REGULAR: &[u8] =
126-
include_bytes!("static/fonts/SourceCodePro-Regular.ttf.woff2");
127-
128-
/// The file `SourceCodePro-Semibold.ttf.woff2`, the Semibold variant of the Source Code Pro
129-
/// font in woff2.
130-
pub(crate) static SEMIBOLD: &[u8] =
131-
include_bytes!("static/fonts/SourceCodePro-Semibold.ttf.woff2");
132-
133-
/// The file `SourceCodePro-It.ttf.woff2`, the Italic variant of the Source Code Pro font in
134-
/// woff2.
135-
pub(crate) static ITALIC: &[u8] = include_bytes!("static/fonts/SourceCodePro-It.ttf.woff2");
44+
/// Insert the provided suffix into a filename just before the extension.
45+
pub(crate) fn suffix_path(filename: &str, suffix: &str) -> PathBuf {
46+
// We use splitn vs Path::extension here because we might get a filename
47+
// like `style.min.css` and we want to process that into
48+
// `style-suffix.min.css`. Path::extension would just return `css`
49+
// which would result in `style.min-suffix.css` which isn't what we
50+
// want.
51+
let (base, ext) = filename.split_once('.').unwrap();
52+
let filename = format!("{}{}.{}", base, suffix, ext);
53+
filename.into()
54+
}
13655

137-
/// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font.
138-
pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/SourceCodePro-LICENSE.txt");
56+
pub(crate) fn static_filename(filename: &str, contents: &[u8]) -> PathBuf {
57+
let filename = filename.rsplit("/").next().unwrap();
58+
suffix_path(filename, &static_suffix(contents))
13959
}
14060

141-
/// Files related to the Nanum Barun Gothic font.
142-
///
143-
/// These files are used to avoid some legacy CJK serif fonts in Windows.
144-
///
145-
/// Note that the Noto Sans KR font, which was used previously but was not very readable on Windows,
146-
/// has been replaced by the Nanum Barun Gothic font. This is due to Windows' implementation of font
147-
/// rendering that distorts OpenType fonts too much.
148-
///
149-
/// The font files were generated with these commands:
150-
///
151-
/// ```sh
152-
/// pyftsubset NanumBarunGothic.ttf \
153-
/// --unicodes=U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF \
154-
/// --output-file=NanumBarunGothic.ttf.woff2 --flavor=woff2
155-
/// ```
156-
pub(crate) mod nanum_barun_gothic {
157-
/// The file `NanumBarunGothic.ttf.woff2`, the Regular variant of the Nanum Barun Gothic font.
158-
pub(crate) static REGULAR: &[u8] = include_bytes!("static/fonts/NanumBarunGothic.ttf.woff2");
61+
fn static_suffix(bytes: &[u8]) -> String {
62+
let mut hasher = FxHasher::default();
63+
hasher.write(bytes);
64+
format!("-{:016x}", hasher.finish())
65+
}
15966

160-
/// The file `NanumBarunGothic-LICENSE.txt`, the license text of the Nanum Barun Gothic font.
161-
pub(crate) static LICENSE: &[u8] = include_bytes!("static/fonts/NanumBarunGothic-LICENSE.txt");
67+
macro_rules! static_files {
68+
($($field:ident => $file_path:literal,)+) => {
69+
pub(crate) struct StaticFiles {
70+
$(pub $field: StaticFile,)+
71+
}
72+
73+
pub(crate) static STATIC_FILES: std::sync::LazyLock<StaticFiles> = std::sync::LazyLock::new(|| StaticFiles {
74+
$($field: StaticFile::new($file_path, include_bytes!($file_path)),)+
75+
});
76+
77+
pub(crate) fn for_each<E>(f: impl Fn(&StaticFile) -> Result<(), E>) -> Result<(), E> {
78+
for sf in [
79+
$(&STATIC_FILES.$field,)+
80+
] {
81+
f(sf)?
82+
}
83+
Ok(())
84+
}
85+
}
16286
}
16387

164-
/// Files related to the sidebar in rustdoc sources.
165-
pub(crate) mod sidebar {
166-
/// File script to handle sidebar.
167-
pub(crate) static SOURCE_SCRIPT: &str = include_str!("static/js/source-script.js");
88+
static_files! {
89+
rustdoc_css => "static/css/rustdoc.css",
90+
settings_css => "static/css/settings.css",
91+
noscript_css => "static/css/noscript.css",
92+
normalize_css => "static/css/normalize.css",
93+
main_js => "static/js/main.js",
94+
search_js => "static/js/search.js",
95+
settings_js => "static/js/settings.js",
96+
source_script_js => "static/js/source-script.js",
97+
storage_js => "static/js/storage.js",
98+
scrape_examples_js => "static/js/scrape-examples.js",
99+
wheel_svg => "static/images/wheel.svg",
100+
clipboard_svg => "static/images/clipboard.svg",
101+
down_arrow_svg => "static/images/down-arrow.svg",
102+
toggle_minus_png => "static/images/toggle-minus.svg",
103+
toggle_plus_png => "static/images/toggle-plus.svg",
104+
copyright => "static/COPYRIGHT.txt",
105+
license_apache => "static/LICENSE-APACHE.txt",
106+
license_mit => "static/LICENSE-MIT.txt",
107+
rust_logo_svg => "static/images/rust-logo.svg",
108+
rust_favicon_svg => "static/images/favicon.svg",
109+
rust_favicon_png_16 => "static/images/favicon-16x16.png",
110+
rust_favicon_png_32 => "static/images/favicon-32x32.png",
111+
theme_light_css => "static/css/themes/light.css",
112+
theme_dark_css => "static/css/themes/dark.css",
113+
theme_ayu_css => "static/css/themes/ayu.css",
114+
fira_sans_regular => "static/fonts/FiraSans-Regular.woff2",
115+
fira_sans_medium => "static/fonts/FiraSans-Medium.woff2",
116+
fira_sans_license => "static/fonts/FiraSans-LICENSE.txt",
117+
source_serif_4_regular => "static/fonts/SourceSerif4-Regular.ttf.woff2",
118+
source_serif_4_bold => "static/fonts/SourceSerif4-Bold.ttf.woff2",
119+
source_serif_4_italic => "static/fonts/SourceSerif4-It.ttf.woff2",
120+
source_serif_4_license => "static/fonts/SourceSerif4-LICENSE.md",
121+
source_code_pro_regular => "static/fonts/SourceCodePro-Regular.ttf.woff2",
122+
source_code_pro_semibold => "static/fonts/SourceCodePro-Semibold.ttf.woff2",
123+
source_code_pro_italic => "static/fonts/SourceCodePro-It.ttf.woff2",
124+
source_code_pro_license => "static/fonts/SourceCodePro-LICENSE.txt",
125+
nanum_barun_gothic_regular => "static/fonts/NanumBarunGothic.ttf.woff2",
126+
nanum_barun_gothic_license => "static/fonts/NanumBarunGothic-LICENSE.txt",
168127
}
128+
129+
pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/js/scrape-examples.js");

‎src/librustdoc/html/templates/page.html

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,48 +7,44 @@
77
<meta name="description" content="{{page.description}}"> {#- -#}
88
<meta name="keywords" content="{{page.keywords}}"> {#- -#}
99
<title>{{page.title}}</title> {#- -#}
10-
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceSerif4-Regular.ttf.woff2"> {#- -#}
11-
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}FiraSans-Regular.woff2"> {#- -#}
12-
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}FiraSans-Medium.woff2"> {#- -#}
13-
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceCodePro-Regular.ttf.woff2"> {#- -#}
14-
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceSerif4-Bold.ttf.woff2"> {#- -#}
15-
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceCodePro-Semibold.ttf.woff2"> {#- -#}
10+
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_serif_4_regular}}"> {#- -#}
11+
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_regular}}"> {#- -#}
12+
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_medium}}"> {#- -#}
13+
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_code_pro_regular}}"> {#- -#}
14+
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_serif_4_bold}}"> {#- -#}
15+
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_code_pro_semibold}}"> {#- -#}
1616
<link rel="stylesheet" {# -#}
17-
href="{{static_root_path|safe}}normalize{{page.resource_suffix}}.css"> {#- -#}
17+
href="{{static_root_path|safe}}{{files.normalize_css}}"> {#- -#}
1818
<link rel="stylesheet" {# -#}
19-
href="{{static_root_path|safe}}rustdoc{{page.resource_suffix}}.css" {# -#}
19+
href="{{static_root_path|safe}}{{files.rustdoc_css}}" {# -#}
2020
id="mainThemeStyle"> {#- -#}
21+
<link rel="stylesheet" id="themeStyle" href="{{static_root_path|safe}}{{files.theme_light_css}}"> {#- -#}
22+
<link rel="stylesheet" disabled href="{{static_root_path|safe}}{{files.theme_dark_css}}"> {#- -#}
23+
<link rel="stylesheet" disabled href="{{static_root_path|safe}}{{files.theme_ayu_css}}"> {#- -#}
2124
{%- for theme in themes -%}
22-
<link rel="stylesheet" {# -#}
23-
href="{{static_root_path|safe}}{{theme}}{{page.resource_suffix}}.css" {# -#}
24-
{%- if theme == "light" -%}
25-
id="themeStyle"
26-
{%- else -%}
27-
disabled
28-
{%- endif -%}
29-
>
25+
<link rel="stylesheet" disabled href="{{page.root_path|safe}}{{theme}}{{page.resource_suffix}}.css"> {#- -#}
3026
{%- endfor -%}
3127
<script id="default-settings" {# -#}
3228
{% for (k, v) in layout.default_settings %}
3329
data-{{k}}="{{v}}"
3430
{%- endfor -%}
3531
></script> {#- -#}
36-
<script src="{{static_root_path|safe}}storage{{page.resource_suffix}}.js"></script> {#- -#}
32+
<script src="{{static_root_path|safe}}{{files.storage_js}}"></script> {#- -#}
3733
{%- if page.css_class.contains("crate") -%}
3834
<script defer src="{{page.root_path|safe}}crates{{page.resource_suffix}}.js"></script> {#- -#}
3935
{%- else if page.css_class == "source" -%}
40-
<script defer src="{{static_root_path|safe}}source-script{{page.resource_suffix}}.js"></script> {#- -#}
36+
<script defer src="{{static_root_path|safe}}{{files.source_script_js}}"></script> {#- -#}
4137
<script defer src="{{page.root_path|safe}}source-files{{page.resource_suffix}}.js"></script> {#- -#}
4238
{%- else if !page.css_class.contains("mod") -%}
4339
<script defer src="sidebar-items{{page.resource_suffix}}.js"></script> {#- -#}
4440
{%- endif -%}
45-
<script defer src="{{static_root_path|safe}}main{{page.resource_suffix}}.js"></script> {#- -#}
41+
<script defer src="{{static_root_path|safe}}{{files.main_js}}"></script> {#- -#}
4642
{%- if layout.scrape_examples_extension -%}
47-
<script defer src="{{page.root_path|safe}}scrape-examples{{page.resource_suffix}}.js"></script> {#- -#}
43+
<script defer src="{{page.root_path|safe}}{{files.scrape_examples_js}}"></script> {#- -#}
4844
{%- endif -%}
4945
<noscript> {#- -#}
5046
<link rel="stylesheet" {# -#}
51-
href="{{static_root_path|safe}}noscript{{page.resource_suffix}}.css"> {#- -#}
47+
href="{{static_root_path|safe}}{{files.noscript_css}}"> {#- -#}
5248
</noscript> {#- -#}
5349
{%- if layout.css_file_extension.is_some() -%}
5450
<link rel="stylesheet" {# -#}
@@ -58,11 +54,11 @@
5854
<link rel="icon" href="{{layout.favicon}}"> {#- -#}
5955
{%- else -%}
6056
<link rel="alternate icon" type="image/png" {# -#}
61-
href="{{static_root_path|safe}}favicon-16x16{{page.resource_suffix}}.png"> {#- -#}
57+
href="{{static_root_path|safe}}{{files.rust_favicon_png_16}}"> {#- -#}
6258
<link rel="alternate icon" type="image/png" {# -#}
63-
href="{{static_root_path|safe}}favicon-32x32{{page.resource_suffix}}.png"> {#- -#}
59+
href="{{static_root_path|safe}}{{files.rust_favicon_png_32}}"> {#- -#}
6460
<link rel="icon" type="image/svg+xml" {# -#}
65-
href="{{static_root_path|safe}}favicon{{page.resource_suffix}}.svg"> {#- -#}
61+
href="{{static_root_path|safe}}{{files.rust_favicon_svg}}"> {#- -#}
6662
{%- endif -%}
6763
{{- layout.external_html.in_header|safe -}}
6864
</head> {#- -#}
@@ -81,7 +77,7 @@
8177
{%- if !layout.logo.is_empty() -%}
8278
<img src="{{layout.logo}}" alt="logo"> {#- -#}
8379
{%- else -%}
84-
<img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.svg" alt="logo"> {#- -#}
80+
<img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#}
8581
{%- endif -%}
8682
</div> {#- -#}
8783
</a> {#- -#}
@@ -95,7 +91,7 @@ <h2></h2> {#- -#}
9591
{%- if !layout.logo.is_empty() %}
9692
<img src="{{layout.logo}}" alt="logo"> {#- -#}
9793
{%- else -%}
98-
<img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.svg" alt="logo"> {#- -#}
94+
<img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#}
9995
{%- endif -%}
10096
</div> {#- -#}
10197
</a> {#- -#}
@@ -110,7 +106,7 @@ <h2></h2> {#- -#}
110106
{%- if !layout.logo.is_empty() %}
111107
<img src="{{layout.logo}}" alt="logo"> {#- -#}
112108
{%- else -%}
113-
<img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.svg" alt="logo"> {#- -#}
109+
<img class="rust-logo" src="{{static_root_path|safe}}{{files.rust_logo_svg}}" alt="logo"> {#- -#}
114110
{%- endif -%}
115111
</a> {#- -#}
116112
{%- endif -%}
@@ -129,7 +125,7 @@ <h2></h2> {#- -#}
129125
<div id="settings-menu" tabindex="-1"> {#- -#}
130126
<a href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#}
131127
<img width="22" height="22" alt="Change settings" {# -#}
132-
src="{{static_root_path|safe}}wheel{{page.resource_suffix}}.svg"> {#- -#}
128+
src="{{static_root_path|safe}}{{files.wheel_svg}}"> {#- -#}
133129
</a> {#- -#}
134130
</div> {#- -#}
135131
</form> {#- -#}
@@ -140,10 +136,14 @@ <h2></h2> {#- -#}
140136
{{- layout.external_html.after_content|safe -}}
141137
<div id="rustdoc-vars" {# -#}
142138
data-root-path="{{page.root_path|safe}}" {# -#}
139+
data-static-root-path="{{static_root_path|safe}}" {# -#}
143140
data-current-crate="{{layout.krate}}" {# -#}
144141
data-themes="{{themes|join(",") }}" {# -#}
145142
data-resource-suffix="{{page.resource_suffix}}" {# -#}
146143
data-rustdoc-version="{{rustdoc_version}}" {# -#}
144+
data-search-js="{{files.search_js}}" {# -#}
145+
data-settings-js="{{files.settings_js}}" {# -#}
146+
data-settings-css="{{files.settings_css}}" {# -#}
147147
> {#- -#}
148148
</div> {#- -#}
149149
</body> {#- -#}

‎src/librustdoc/html/templates/print_item.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ <h1 class="fqn"> {#- -#}
77
{%- endfor -%}
88
<a class="{{item_type}}" href="#">{{name}}</a> {#- -#}
99
<button id="copy-path" onclick="copy_path(this)" title="Copy item path to clipboard"> {#- -#}
10-
<img src="{{static_root_path|safe}}clipboard{{page.resource_suffix}}.svg" {# -#}
10+
<img src="{{static_root_path|safe}}{{clipboard_svg}}" {# -#}
1111
width="19" height="18" {# -#}
1212
alt="Copy item path"> {#- -#}
1313
</button> {#- -#}

‎src/librustdoc/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -469,9 +469,6 @@ fn opts() -> Vec<RustcOptGroup> {
469469
stable("json", |o| {
470470
o.optopt("", "json", "Configure the structure of JSON diagnostics", "CONFIG")
471471
}),
472-
unstable("disable-minification", |o| {
473-
o.optflagmulti("", "disable-minification", "Disable minification applied on JS files")
474-
}),
475472
stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "LINT")),
476473
stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "LINT")),
477474
stable("force-warn", |o| o.optmulti("", "force-warn", "Set lint force-warn", "LINT")),
@@ -610,6 +607,7 @@ fn opts() -> Vec<RustcOptGroup> {
610607
)
611608
}),
612609
// deprecated / removed options
610+
unstable("disable-minification", |o| o.optflagmulti("", "disable-minification", "removed")),
613611
stable("plugin-path", |o| {
614612
o.optmulti(
615613
"",

‎src/test/run-make/emit-shared-files/Makefile

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,24 @@ invocation-only:
2323

2424
toolchain-only:
2525
$(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources --output $(TOOLCHAIN_ONLY) --resource-suffix=-xxx --extend-css z.css x.rs
26-
[ -e $(TOOLCHAIN_ONLY)/storage-xxx.js ]
27-
! [ -e $(TOOLCHAIN_ONLY)/SourceSerif4-It.ttf.woff2 ]
26+
[ -e $(TOOLCHAIN_ONLY)/static.files/storage-*.js ]
27+
[ -e $(TOOLCHAIN_ONLY)/static.files/SourceSerif4-It-*.ttf.woff2 ]
2828
! [ -e $(TOOLCHAIN_ONLY)/search-index-xxx.js ]
2929
! [ -e $(TOOLCHAIN_ONLY)/x/index.html ]
3030
! [ -e $(TOOLCHAIN_ONLY)/theme.css ]
3131

32-
[ -e $(TOOLCHAIN_ONLY)/main-xxx.js ]
32+
[ -e $(TOOLCHAIN_ONLY)/static.files/main-*.js ]
3333
! [ -e $(TOOLCHAIN_ONLY)/y-xxx.css ]
3434

3535
all-shared:
3636
$(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources,unversioned-shared-resources --output $(ALL_SHARED) --resource-suffix=-xxx --extend-css z.css x.rs
37-
[ -e $(ALL_SHARED)/storage-xxx.js ]
38-
[ -e $(ALL_SHARED)/SourceSerif4-It.ttf.woff2 ]
37+
[ -e $(ALL_SHARED)/static.files/storage-*.js ]
38+
[ -e $(ALL_SHARED)/static.files/SourceSerif4-It-*.ttf.woff2 ]
3939
! [ -e $(ALL_SHARED)/search-index-xxx.js ]
4040
! [ -e $(ALL_SHARED)/settings.html ]
4141
! [ -e $(ALL_SHARED)/x ]
4242
! [ -e $(ALL_SHARED)/src ]
4343
! [ -e $(ALL_SHARED)/theme.css ]
4444

45-
[ -e $(ALL_SHARED)/main-xxx.js ]
45+
[ -e $(ALL_SHARED)/static.files/main-*.js ]
4646
! [ -e $(ALL_SHARED)/y-xxx.css ]

‎src/test/run-make/issue-88756-default-output/output-default.stdout

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,6 @@ Options:
115115
Provide width of the output for truncated error
116116
messages
117117
--json CONFIG Configure the structure of JSON diagnostics
118-
--disable-minification
119-
Disable minification applied on JS files
120118
-A, --allow LINT Set lint allowed
121119
-W, --warn LINT Set lint warnings
122120
--force-warn LINT
@@ -173,6 +171,8 @@ Options:
173171
--scrape-tests Include test code when scraping examples
174172
--with-examples path to function call information (for displaying examples in the documentation)
175173

174+
--disable-minification
175+
removed
176176
--plugin-path DIR
177177
removed, see issue #44136
178178
<https://github.com/rust-lang/rust/issues/44136> for

‎src/test/rustdoc-gui/search-result-color.goml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ assert-css: (
7878
// Checking the color of the bottom border.
7979
assert-css: (
8080
".search-results > a",
81-
{"border-bottom-color": "rgb(92, 103, 115)"}
81+
{"border-bottom-color": "rgba(170, 170, 170, 0.2)"}
8282
)
8383

8484
// Checking the color of "keyword" text.
@@ -190,7 +190,7 @@ assert-css: (
190190
// Checking the color of the bottom border.
191191
assert-css: (
192192
".search-results > a",
193-
{"border-bottom-color": "rgb(224, 224, 224)"}
193+
{"border-bottom-color": "rgba(170, 170, 170, 0.2)"}
194194
)
195195

196196
// Checking the color for "keyword" text.
@@ -287,7 +287,7 @@ assert-css: (
287287
// Checking the color of the bottom border.
288288
assert-css: (
289289
".search-results > a",
290-
{"border-bottom-color": "rgb(224, 224, 224)"}
290+
{"border-bottom-color": "rgba(170, 170, 170, 0.2)"}
291291
)
292292

293293
// Checking the color for "keyword" text.

‎src/test/rustdoc/static-root-path.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
// compile-flags:-Z unstable-options --static-root-path /cache/
22

33
// @has static_root_path/struct.SomeStruct.html
4-
// @matchesraw - '"/cache/main\.js"'
5-
// @!matchesraw - '"\.\./main\.js"'
4+
// @matchesraw - '"/cache/main-'
5+
// @!matchesraw - '"\.\./main'
66
// @matchesraw - 'data-root-path="\.\./"'
77
// @!matchesraw - '"/cache/search-index\.js"'
88
pub struct SomeStruct;
99

1010
// @has src/static_root_path/static-root-path.rs.html
11-
// @matchesraw - '"/cache/source-script\.js"'
12-
// @!matchesraw - '"\.\./\.\./source-script\.js"'
11+
// @matchesraw - '"/cache/source-script-'
12+
// @!matchesraw - '"\.\./\.\./source-script'
1313
// @matchesraw - '"\.\./\.\./source-files.js"'
1414
// @!matchesraw - '"/cache/source-files\.js"'
1515

1616
// @has settings.html
17-
// @matchesraw - '/cache/settings\.js'
18-
// @!matchesraw - '\./settings\.js'
17+
// @matchesraw - '/cache/settings-'
18+
// @!matchesraw - '\../settings'
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![allow(unused_variables)]
2+
use std::fs::File;
3+
4+
fn main() {
5+
if Err(err) = File::open("hello.txt") {
6+
//~^ ERROR: cannot find value `err` in this scope
7+
//~| ERROR: mismatched types
8+
}
9+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0425]: cannot find value `err` in this scope
2+
--> $DIR/issue-103909.rs:5:12
3+
|
4+
LL | if Err(err) = File::open("hello.txt") {
5+
| ^^^ not found in this scope
6+
|
7+
help: you might have meant to use pattern matching
8+
|
9+
LL | if let Err(err) = File::open("hello.txt") {
10+
| +++
11+
12+
error[E0308]: mismatched types
13+
--> $DIR/issue-103909.rs:5:8
14+
|
15+
LL | if Err(err) = File::open("hello.txt") {
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
17+
18+
error: aborting due to 2 previous errors
19+
20+
Some errors have detailed explanations: E0308, E0425.
21+
For more information about an error, try `rustc --explain E0308`.

‎src/tools/rustdoc-js/tester.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,10 +307,13 @@ function runChecks(testFile, doSearch, parseQuery) {
307307
* `parseQuery` function exported from the search module.
308308
*/
309309
function loadSearchJS(doc_folder, resource_suffix) {
310-
const searchJs = path.join(doc_folder, "search" + resource_suffix + ".js");
311310
const searchIndexJs = path.join(doc_folder, "search-index" + resource_suffix + ".js");
312311
const searchIndex = require(searchIndexJs);
313-
const searchModule = require(searchJs);
312+
313+
const staticFiles = path.join(doc_folder, "static.files");
314+
const searchJs = fs.readdirSync(staticFiles).find(
315+
f => f.match(/search.*\.js$/));
316+
const searchModule = require(path.join(staticFiles, searchJs));
314317
const searchWords = searchModule.initSearch(searchIndex.searchIndex);
315318

316319
return {

0 commit comments

Comments
 (0)
This repository has been archived.