@@ -14,7 +14,7 @@ use serde::Serialize;
14
14
use super :: { collect_paths_for_type, ensure_trailing_slash, Context , BASIC_KEYWORDS } ;
15
15
use crate :: clean:: Crate ;
16
16
use crate :: config:: RenderOptions ;
17
- use crate :: docfs:: { DocFS , PathError } ;
17
+ use crate :: docfs:: PathError ;
18
18
use crate :: error:: Error ;
19
19
use crate :: formats:: FormatRenderer ;
20
20
use crate :: html:: { layout, static_files} ;
@@ -40,6 +40,81 @@ crate static FILES_UNVERSIONED: Lazy<FxHashMap<&str, &[u8]>> = Lazy::new(|| {
40
40
}
41
41
} ) ;
42
42
43
+ enum SharedResource < ' a > {
44
+ /// This file will never change, no matter what toolchain is used to build it.
45
+ ///
46
+ /// It does not have a resource suffix.
47
+ Unversioned { name : & ' a str } ,
48
+ /// This file may change depending on the toolchain.
49
+ ///
50
+ /// It has a resource suffix.
51
+ ToolchainSpecific { basename : & ' a str } ,
52
+ /// This file may change for any crate within a build.
53
+ ///
54
+ /// This differs from normal crate-specific files because it has a resource suffix.
55
+ CrateSpecific { basename : & ' a str } ,
56
+ }
57
+
58
+ impl SharedResource < ' _ > {
59
+ fn extension ( & self ) -> Option < & OsStr > {
60
+ use SharedResource :: * ;
61
+ match self {
62
+ Unversioned { name }
63
+ | ToolchainSpecific { basename : name }
64
+ | CrateSpecific { basename : name } => Path :: new ( name) . extension ( ) ,
65
+ }
66
+ }
67
+
68
+ fn path ( & self , cx : & Context < ' _ > ) -> PathBuf {
69
+ match self {
70
+ SharedResource :: Unversioned { name } => cx. dst . join ( name) ,
71
+ SharedResource :: ToolchainSpecific { basename } => cx. suffix_path ( basename) ,
72
+ SharedResource :: CrateSpecific { basename } => cx. suffix_path ( basename) ,
73
+ }
74
+ }
75
+ }
76
+
77
+ impl Context < ' _ > {
78
+ fn suffix_path ( & self , filename : & str ) -> PathBuf {
79
+ // We use splitn vs Path::extension here because we might get a filename
80
+ // like `style.min.css` and we want to process that into
81
+ // `style-suffix.min.css`. Path::extension would just return `css`
82
+ // which would result in `style.min-suffix.css` which isn't what we
83
+ // want.
84
+ let ( base, ext) = filename. split_once ( '.' ) . unwrap ( ) ;
85
+ let filename = format ! ( "{}{}.{}" , base, self . shared. resource_suffix, ext) ;
86
+ self . dst . join ( & filename)
87
+ }
88
+
89
+ fn write_shared < C : AsRef < [ u8 ] > > ( & self , resource : SharedResource < ' _ > , contents : C ) -> Result < ( ) , Error >
90
+ {
91
+ self . shared . fs . write ( resource. path ( self ) , contents)
92
+ }
93
+
94
+ fn write_minify (
95
+ & self ,
96
+ resource : SharedResource < ' _ > ,
97
+ contents : & str ,
98
+ minify : bool ,
99
+ ) -> Result < ( ) , Error > {
100
+ let tmp;
101
+ let contents = if minify {
102
+ tmp = if resource. extension ( ) == Some ( & OsStr :: new ( "css" ) ) {
103
+ minifier:: css:: minify ( contents) . map_err ( |e| {
104
+ Error :: new ( format ! ( "failed to minify CSS file: {}" , e) , resource. path ( self ) )
105
+ } ) ?
106
+ } else {
107
+ minifier:: js:: minify ( contents)
108
+ } ;
109
+ tmp. as_bytes ( )
110
+ } else {
111
+ contents. as_bytes ( )
112
+ } ;
113
+
114
+ self . write_shared ( resource, contents)
115
+ }
116
+ }
117
+
43
118
pub ( super ) fn write_shared (
44
119
cx : & Context < ' _ > ,
45
120
krate : & Crate ,
@@ -52,27 +127,22 @@ pub(super) fn write_shared(
52
127
let lock_file = cx. dst . join ( ".lock" ) ;
53
128
let _lock = try_err ! ( flock:: Lock :: new( & lock_file, true , true , true ) , & lock_file) ;
54
129
130
+ // The weird `: &_` is to work around a borrowck bug: https://github.com/rust-lang/rust/issues/41078#issuecomment-293646723
131
+ let write_minify = |p, c : & _ | {
132
+ cx. write_minify (
133
+ SharedResource :: ToolchainSpecific { basename : p } ,
134
+ c,
135
+ options. enable_minification ,
136
+ )
137
+ } ;
138
+ let write_toolchain =
139
+ |p : & _ , c : & _ | cx. write_shared ( SharedResource :: ToolchainSpecific { basename : p } , c) ;
140
+
55
141
// Add all the static files. These may already exist, but we just
56
142
// overwrite them anyway to make sure that they're fresh and up-to-date.
57
-
58
- write_minify (
59
- & cx. shared . fs ,
60
- cx. path ( "rustdoc.css" ) ,
61
- static_files:: RUSTDOC_CSS ,
62
- options. enable_minification ,
63
- ) ?;
64
- write_minify (
65
- & cx. shared . fs ,
66
- cx. path ( "settings.css" ) ,
67
- static_files:: SETTINGS_CSS ,
68
- options. enable_minification ,
69
- ) ?;
70
- write_minify (
71
- & cx. shared . fs ,
72
- cx. path ( "noscript.css" ) ,
73
- static_files:: NOSCRIPT_CSS ,
74
- options. enable_minification ,
75
- ) ?;
143
+ write_minify ( "rustdoc.css" , static_files:: RUSTDOC_CSS ) ?;
144
+ write_minify ( "settings.css" , static_files:: SETTINGS_CSS ) ?;
145
+ write_minify ( "noscript.css" , static_files:: NOSCRIPT_CSS ) ?;
76
146
77
147
// To avoid "light.css" to be overwritten, we'll first run over the received themes and only
78
148
// then we'll run over the "official" styles.
@@ -85,106 +155,66 @@ pub(super) fn write_shared(
85
155
86
156
// Handle the official themes
87
157
match theme {
88
- "light" => write_minify (
89
- & cx. shared . fs ,
90
- cx. path ( "light.css" ) ,
91
- static_files:: themes:: LIGHT ,
92
- options. enable_minification ,
93
- ) ?,
94
- "dark" => write_minify (
95
- & cx. shared . fs ,
96
- cx. path ( "dark.css" ) ,
97
- static_files:: themes:: DARK ,
98
- options. enable_minification ,
99
- ) ?,
100
- "ayu" => write_minify (
101
- & cx. shared . fs ,
102
- cx. path ( "ayu.css" ) ,
103
- static_files:: themes:: AYU ,
104
- options. enable_minification ,
105
- ) ?,
158
+ "light" => write_minify ( "light.css" , static_files:: themes:: LIGHT ) ?,
159
+ "dark" => write_minify ( "dark.css" , static_files:: themes:: DARK ) ?,
160
+ "ayu" => write_minify ( "ayu.css" , static_files:: themes:: AYU ) ?,
106
161
_ => {
107
162
// Handle added third-party themes
108
163
let content = try_err ! ( fs:: read( & entry. path) , & entry. path) ;
109
- cx . shared
110
- . fs
111
- . write ( cx . path ( & format ! ( "{}.{}" , theme, extension) ) , content. as_slice ( ) ) ?;
164
+ // This is not exactly right: if compiled a second time with the same toolchain but different CLI args, the file could be different.
165
+ // But docs.rs doesn't use this, so hopefully the issue doesn't come up.
166
+ write_toolchain ( & format ! ( "{}.{}" , theme, extension) , content. as_slice ( ) ) ?;
112
167
}
113
168
} ;
114
169
115
170
themes. insert ( theme. to_owned ( ) ) ;
116
171
}
117
172
118
- let write = |p, c| cx. shared . fs . write ( p, c) ;
119
173
if ( * cx. shared ) . layout . logo . is_empty ( ) {
120
- write ( cx . path ( "rust-logo.png" ) , static_files:: RUST_LOGO ) ?;
174
+ write_toolchain ( "rust-logo.png" , static_files:: RUST_LOGO ) ?;
121
175
}
122
176
if ( * cx. shared ) . layout . favicon . is_empty ( ) {
123
- write ( cx . path ( "favicon.svg" ) , static_files:: RUST_FAVICON_SVG ) ?;
124
- write ( cx . path ( "favicon-16x16.png" ) , static_files:: RUST_FAVICON_PNG_16 ) ?;
125
- write ( cx . path ( "favicon-32x32.png" ) , static_files:: RUST_FAVICON_PNG_32 ) ?;
177
+ write_toolchain ( "favicon.svg" , static_files:: RUST_FAVICON_SVG ) ?;
178
+ write_toolchain ( "favicon-16x16.png" , static_files:: RUST_FAVICON_PNG_16 ) ?;
179
+ write_toolchain ( "favicon-32x32.png" , static_files:: RUST_FAVICON_PNG_32 ) ?;
126
180
}
127
- write ( cx . path ( "brush.svg" ) , static_files:: BRUSH_SVG ) ?;
128
- write ( cx . path ( "wheel.svg" ) , static_files:: WHEEL_SVG ) ?;
129
- write ( cx . path ( "down-arrow.svg" ) , static_files:: DOWN_ARROW_SVG ) ?;
181
+ write_toolchain ( "brush.svg" , static_files:: BRUSH_SVG ) ?;
182
+ write_toolchain ( "wheel.svg" , static_files:: WHEEL_SVG ) ?;
183
+ write_toolchain ( "down-arrow.svg" , static_files:: DOWN_ARROW_SVG ) ?;
130
184
131
185
let mut themes: Vec < & String > = themes. iter ( ) . collect ( ) ;
132
186
themes. sort ( ) ;
133
187
134
188
write_minify (
135
- & cx. shared . fs ,
136
- cx. path ( "main.js" ) ,
189
+ "main.js" ,
137
190
& static_files:: MAIN_JS . replace (
138
191
"/* INSERT THEMES HERE */" ,
139
192
& format ! ( " = {}" , serde_json:: to_string( & themes) . unwrap( ) ) ,
140
193
) ,
141
- options. enable_minification ,
142
- ) ?;
143
- write_minify (
144
- & cx. shared . fs ,
145
- cx. path ( "settings.js" ) ,
146
- static_files:: SETTINGS_JS ,
147
- options. enable_minification ,
148
194
) ?;
195
+ write_minify ( "settings.js" , static_files:: SETTINGS_JS ) ?;
149
196
if cx. shared . include_sources {
150
- write_minify (
151
- & cx. shared . fs ,
152
- cx. path ( "source-script.js" ) ,
153
- static_files:: sidebar:: SOURCE_SCRIPT ,
154
- options. enable_minification ,
155
- ) ?;
197
+ write_minify ( "source-script.js" , static_files:: sidebar:: SOURCE_SCRIPT ) ?;
156
198
}
157
199
158
200
{
159
201
write_minify (
160
- & cx. shared . fs ,
161
- cx. path ( "storage.js" ) ,
202
+ "storage.js" ,
162
203
& format ! (
163
204
"var resourcesSuffix = \" {}\" ;{}" ,
164
205
cx. shared. resource_suffix,
165
206
static_files:: STORAGE_JS
166
207
) ,
167
- options. enable_minification ,
168
208
) ?;
169
209
}
170
210
171
211
if let Some ( ref css) = cx. shared . layout . css_file_extension {
172
- let out = cx. path ( "theme.css" ) ;
173
212
let buffer = try_err ! ( fs:: read_to_string( css) , css) ;
174
- if !options. enable_minification {
175
- cx. shared . fs . write ( & out, & buffer) ?;
176
- } else {
177
- write_minify ( & cx. shared . fs , out, & buffer, options. enable_minification ) ?;
178
- }
213
+ write_minify ( "theme.css" , & buffer) ?;
179
214
}
180
- write_minify (
181
- & cx. shared . fs ,
182
- cx. path ( "normalize.css" ) ,
183
- static_files:: NORMALIZE_CSS ,
184
- options. enable_minification ,
185
- ) ?;
186
- for ( file, contents) in & * FILES_UNVERSIONED {
187
- write ( cx. dst . join ( file) , contents) ?;
215
+ write_minify ( "normalize.css" , static_files:: NORMALIZE_CSS ) ?;
216
+ for ( name, contents) in & * FILES_UNVERSIONED {
217
+ cx. write_shared ( SharedResource :: Unversioned { name } , contents) ?;
188
218
}
189
219
190
220
fn collect ( path : & Path , krate : & str , key : & str ) -> io:: Result < ( Vec < String > , Vec < String > ) > {
@@ -324,7 +354,7 @@ pub(super) fn write_shared(
324
354
"var N = null;var sourcesIndex = {{}};\n {}\n createSourceSidebar();\n " ,
325
355
all_sources. join( "\n " )
326
356
) ;
327
- cx. shared . fs . write ( & dst , v. as_bytes ( ) ) ?;
357
+ cx. write_shared ( SharedResource :: CrateSpecific { basename : "source-files.js" } , v) ?;
328
358
}
329
359
330
360
// Update the search index and crate list.
@@ -341,13 +371,12 @@ pub(super) fn write_shared(
341
371
let mut v = String :: from ( "var searchIndex = JSON.parse('{\\ \n " ) ;
342
372
v. push_str ( & all_indexes. join ( ",\\ \n " ) ) ;
343
373
v. push_str ( "\\ \n }');\n initSearch(searchIndex);" ) ;
344
- cx. shared . fs . write ( & dst , & v) ?;
374
+ cx. write_shared ( SharedResource :: CrateSpecific { basename : "search-index.js" } , v) ?;
345
375
}
346
376
347
- let crate_list_dst = cx. dst . join ( & format ! ( "crates{}.js" , cx. shared. resource_suffix) ) ;
348
377
let crate_list =
349
378
format ! ( "window.ALL_CRATES = [{}];" , krates. iter( ) . map( |k| format!( "\" {}\" " , k) ) . join( "," ) ) ;
350
- cx. shared . fs . write ( & crate_list_dst , & crate_list) ?;
379
+ cx. write_shared ( SharedResource :: CrateSpecific { basename : "crates.js" } , crate_list) ?;
351
380
352
381
if options. enable_index_page {
353
382
if let Some ( index_page) = options. index_page . clone ( ) {
@@ -481,21 +510,3 @@ pub(super) fn write_shared(
481
510
}
482
511
Ok ( ( ) )
483
512
}
484
-
485
- fn write_minify (
486
- fs : & DocFS ,
487
- dst : PathBuf ,
488
- contents : & str ,
489
- enable_minification : bool ,
490
- ) -> Result < ( ) , Error > {
491
- if enable_minification {
492
- if dst. extension ( ) == Some ( & OsStr :: new ( "css" ) ) {
493
- let res = try_none ! ( minifier:: css:: minify( contents) . ok( ) , & dst) ;
494
- fs. write ( dst, res. as_bytes ( ) )
495
- } else {
496
- fs. write ( dst, minifier:: js:: minify ( contents) . as_bytes ( ) )
497
- }
498
- } else {
499
- fs. write ( dst, contents. as_bytes ( ) )
500
- }
501
- }
0 commit comments