@@ -2,8 +2,9 @@ use crate::book::{Book, BookItem};
22use crate :: config:: { BookConfig , Code , Config , HtmlConfig , Playground , RustEdition } ;
33use crate :: errors:: * ;
44use crate :: renderer:: html_handlebars:: helpers;
5+ use crate :: renderer:: html_handlebars:: StaticFiles ;
56use crate :: renderer:: { RenderContext , Renderer } ;
6- use crate :: theme:: { self , playground_editor , Theme } ;
7+ use crate :: theme:: { self , Theme } ;
78use crate :: utils;
89
910use std:: borrow:: Cow ;
@@ -222,134 +223,6 @@ impl HtmlHandlebars {
222223 rendered
223224 }
224225
225- fn copy_static_files (
226- & self ,
227- destination : & Path ,
228- theme : & Theme ,
229- html_config : & HtmlConfig ,
230- ) -> Result < ( ) > {
231- use crate :: utils:: fs:: write_file;
232-
233- write_file (
234- destination,
235- ".nojekyll" ,
236- b"This file makes sure that Github Pages doesn't process mdBook's output.\n " ,
237- ) ?;
238-
239- if let Some ( cname) = & html_config. cname {
240- write_file ( destination, "CNAME" , format ! ( "{cname}\n " ) . as_bytes ( ) ) ?;
241- }
242-
243- write_file ( destination, "book.js" , & theme. js ) ?;
244- write_file ( destination, "css/general.css" , & theme. general_css ) ?;
245- write_file ( destination, "css/chrome.css" , & theme. chrome_css ) ?;
246- if html_config. print . enable {
247- write_file ( destination, "css/print.css" , & theme. print_css ) ?;
248- }
249- write_file ( destination, "css/variables.css" , & theme. variables_css ) ?;
250- if let Some ( contents) = & theme. favicon_png {
251- write_file ( destination, "favicon.png" , contents) ?;
252- }
253- if let Some ( contents) = & theme. favicon_svg {
254- write_file ( destination, "favicon.svg" , contents) ?;
255- }
256- write_file ( destination, "highlight.css" , & theme. highlight_css ) ?;
257- write_file ( destination, "tomorrow-night.css" , & theme. tomorrow_night_css ) ?;
258- write_file ( destination, "ayu-highlight.css" , & theme. ayu_highlight_css ) ?;
259- write_file ( destination, "highlight.js" , & theme. highlight_js ) ?;
260- write_file ( destination, "clipboard.min.js" , & theme. clipboard_js ) ?;
261- write_file (
262- destination,
263- "FontAwesome/css/font-awesome.css" ,
264- theme:: FONT_AWESOME ,
265- ) ?;
266- write_file (
267- destination,
268- "FontAwesome/fonts/fontawesome-webfont.eot" ,
269- theme:: FONT_AWESOME_EOT ,
270- ) ?;
271- write_file (
272- destination,
273- "FontAwesome/fonts/fontawesome-webfont.svg" ,
274- theme:: FONT_AWESOME_SVG ,
275- ) ?;
276- write_file (
277- destination,
278- "FontAwesome/fonts/fontawesome-webfont.ttf" ,
279- theme:: FONT_AWESOME_TTF ,
280- ) ?;
281- write_file (
282- destination,
283- "FontAwesome/fonts/fontawesome-webfont.woff" ,
284- theme:: FONT_AWESOME_WOFF ,
285- ) ?;
286- write_file (
287- destination,
288- "FontAwesome/fonts/fontawesome-webfont.woff2" ,
289- theme:: FONT_AWESOME_WOFF2 ,
290- ) ?;
291- write_file (
292- destination,
293- "FontAwesome/fonts/FontAwesome.ttf" ,
294- theme:: FONT_AWESOME_TTF ,
295- ) ?;
296- // Don't copy the stock fonts if the user has specified their own fonts to use.
297- if html_config. copy_fonts && theme. fonts_css . is_none ( ) {
298- write_file ( destination, "fonts/fonts.css" , theme:: fonts:: CSS ) ?;
299- for ( file_name, contents) in theme:: fonts:: LICENSES . iter ( ) {
300- write_file ( destination, file_name, contents) ?;
301- }
302- for ( file_name, contents) in theme:: fonts:: OPEN_SANS . iter ( ) {
303- write_file ( destination, file_name, contents) ?;
304- }
305- write_file (
306- destination,
307- theme:: fonts:: SOURCE_CODE_PRO . 0 ,
308- theme:: fonts:: SOURCE_CODE_PRO . 1 ,
309- ) ?;
310- }
311- if let Some ( fonts_css) = & theme. fonts_css {
312- if !fonts_css. is_empty ( ) {
313- write_file ( destination, "fonts/fonts.css" , fonts_css) ?;
314- }
315- }
316- if !html_config. copy_fonts && theme. fonts_css . is_none ( ) {
317- warn ! (
318- "output.html.copy-fonts is deprecated.\n \
319- This book appears to have copy-fonts=false in book.toml without a fonts.css file.\n \
320- Add an empty `theme/fonts/fonts.css` file to squelch this warning."
321- ) ;
322- }
323- for font_file in & theme. font_files {
324- let contents = fs:: read ( font_file) ?;
325- let filename = font_file. file_name ( ) . unwrap ( ) ;
326- let filename = Path :: new ( "fonts" ) . join ( filename) ;
327- write_file ( destination, filename, & contents) ?;
328- }
329-
330- let playground_config = & html_config. playground ;
331-
332- // Ace is a very large dependency, so only load it when requested
333- if playground_config. editable && playground_config. copy_js {
334- // Load the editor
335- write_file ( destination, "editor.js" , playground_editor:: JS ) ?;
336- write_file ( destination, "ace.js" , playground_editor:: ACE_JS ) ?;
337- write_file ( destination, "mode-rust.js" , playground_editor:: MODE_RUST_JS ) ?;
338- write_file (
339- destination,
340- "theme-dawn.js" ,
341- playground_editor:: THEME_DAWN_JS ,
342- ) ?;
343- write_file (
344- destination,
345- "theme-tomorrow_night.js" ,
346- playground_editor:: THEME_TOMORROW_NIGHT_JS ,
347- ) ?;
348- }
349-
350- Ok ( ( ) )
351- }
352-
353226 /// Update the context with data for this file
354227 fn configure_print_version (
355228 & self ,
@@ -381,43 +254,6 @@ impl HtmlHandlebars {
381254 handlebars. register_helper ( "theme_option" , Box :: new ( helpers:: theme:: theme_option) ) ;
382255 }
383256
384- /// Copy across any additional CSS and JavaScript files which the book
385- /// has been configured to use.
386- fn copy_additional_css_and_js (
387- & self ,
388- html : & HtmlConfig ,
389- root : & Path ,
390- destination : & Path ,
391- ) -> Result < ( ) > {
392- let custom_files = html. additional_css . iter ( ) . chain ( html. additional_js . iter ( ) ) ;
393-
394- debug ! ( "Copying additional CSS and JS" ) ;
395-
396- for custom_file in custom_files {
397- let input_location = root. join ( custom_file) ;
398- let output_location = destination. join ( custom_file) ;
399- if let Some ( parent) = output_location. parent ( ) {
400- fs:: create_dir_all ( parent)
401- . with_context ( || format ! ( "Unable to create {}" , parent. display( ) ) ) ?;
402- }
403- debug ! (
404- "Copying {} -> {}" ,
405- input_location. display( ) ,
406- output_location. display( )
407- ) ;
408-
409- fs:: copy ( & input_location, & output_location) . with_context ( || {
410- format ! (
411- "Unable to copy {} to {}" ,
412- input_location. display( ) ,
413- output_location. display( )
414- )
415- } ) ?;
416- }
417-
418- Ok ( ( ) )
419- }
420-
421257 fn emit_redirects (
422258 & self ,
423259 root : & Path ,
@@ -544,6 +380,57 @@ impl Renderer for HtmlHandlebars {
544380 fs:: create_dir_all ( destination)
545381 . with_context ( || "Unexpected error when constructing destination path" ) ?;
546382
383+ let mut static_files = StaticFiles :: new ( & theme, & html_config, & ctx. root ) ?;
384+
385+ // Render search index
386+ #[ cfg( feature = "search" ) ]
387+ {
388+ let default = crate :: config:: Search :: default ( ) ;
389+ let search = html_config. search . as_ref ( ) . unwrap_or ( & default) ;
390+ if search. enable {
391+ super :: search:: create_files ( & search, & mut static_files, & book) ?;
392+ }
393+ }
394+
395+ debug ! ( "Render toc js" ) ;
396+ {
397+ let rendered_toc = handlebars. render ( "toc_js" , & data) ?;
398+ static_files. add_builtin ( "toc.js" , rendered_toc. as_bytes ( ) ) ;
399+ debug ! ( "Creating toc.js ✓" ) ;
400+ }
401+
402+ if html_config. hash_files {
403+ static_files. hash_files ( ) ?;
404+ }
405+
406+ debug ! ( "Copy static files" ) ;
407+ let resource_helper = static_files
408+ . write_files ( & destination)
409+ . with_context ( || "Unable to copy across static files" ) ?;
410+
411+ handlebars. register_helper ( "resource" , Box :: new ( resource_helper) ) ;
412+
413+ debug ! ( "Render toc html" ) ;
414+ {
415+ data. insert ( "is_toc_html" . to_owned ( ) , json ! ( true ) ) ;
416+ data. insert ( "path" . to_owned ( ) , json ! ( "toc.html" ) ) ;
417+ let rendered_toc = handlebars. render ( "toc_html" , & data) ?;
418+ utils:: fs:: write_file ( destination, "toc.html" , rendered_toc. as_bytes ( ) ) ?;
419+ debug ! ( "Creating toc.html ✓" ) ;
420+ data. remove ( "path" ) ;
421+ data. remove ( "is_toc_html" ) ;
422+ }
423+
424+ utils:: fs:: write_file (
425+ destination,
426+ ".nojekyll" ,
427+ b"This file makes sure that Github Pages doesn't process mdBook's output.\n " ,
428+ ) ?;
429+
430+ if let Some ( cname) = & html_config. cname {
431+ utils:: fs:: write_file ( destination, "CNAME" , format ! ( "{cname}\n " ) . as_bytes ( ) ) ?;
432+ }
433+
547434 let mut is_index = true ;
548435 for item in book. iter ( ) {
549436 let ctx = RenderItemContext {
@@ -588,33 +475,6 @@ impl Renderer for HtmlHandlebars {
588475 debug ! ( "Creating print.html ✓" ) ;
589476 }
590477
591- debug ! ( "Render toc" ) ;
592- {
593- let rendered_toc = handlebars. render ( "toc_js" , & data) ?;
594- utils:: fs:: write_file ( destination, "toc.js" , rendered_toc. as_bytes ( ) ) ?;
595- debug ! ( "Creating toc.js ✓" ) ;
596- data. insert ( "is_toc_html" . to_owned ( ) , json ! ( true ) ) ;
597- let rendered_toc = handlebars. render ( "toc_html" , & data) ?;
598- utils:: fs:: write_file ( destination, "toc.html" , rendered_toc. as_bytes ( ) ) ?;
599- debug ! ( "Creating toc.html ✓" ) ;
600- data. remove ( "is_toc_html" ) ;
601- }
602-
603- debug ! ( "Copy static files" ) ;
604- self . copy_static_files ( destination, & theme, & html_config)
605- . with_context ( || "Unable to copy across static files" ) ?;
606- self . copy_additional_css_and_js ( & html_config, & ctx. root , destination)
607- . with_context ( || "Unable to copy across additional CSS and JS" ) ?;
608-
609- // Render search index
610- #[ cfg( feature = "search" ) ]
611- {
612- let search = html_config. search . unwrap_or_default ( ) ;
613- if search. enable {
614- super :: search:: create_files ( & search, destination, book) ?;
615- }
616- }
617-
618478 self . emit_redirects ( & ctx. destination , & handlebars, & html_config. redirect )
619479 . context ( "Unable to emit redirects" ) ?;
620480
0 commit comments