11use crate :: build;
22use crate :: slide:: Slide ;
33use crate :: Arguments ;
4+ use crate :: Config ;
45use crate :: WatchArgs ;
56use ignore:: Walk ;
67use live_server:: listen;
@@ -13,35 +14,50 @@ use std::path::Path;
1314use std:: path:: PathBuf ;
1415use std:: sync:: mpsc;
1516
17+ /// Add a timestamp to the filename.
18+ ///
19+ /// This is used to bust the browser cache (force update).
1620fn add_timestamp ( filename : & OsStr , timestamp : u64 ) -> String {
1721 let path = Path :: new ( filename) ;
1822 let stem = path. file_stem ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
1923 let extension = path. extension ( ) . unwrap_or_default ( ) . to_str ( ) . unwrap_or ( "" ) ;
2024 format ! ( "{}_{}.{}" , stem, timestamp, extension)
2125}
2226
23- fn core_html ( out_dir : & str , slide : & Slide , timestamp : u64 ) -> String {
24- let video_path = crate :: path:: video_path ( out_dir, slide) ;
25- let filename = video_path. file_name ( ) . unwrap ( ) ;
26- let filename = add_timestamp ( filename, timestamp) ;
27+ fn core_html ( out_dir : & str , slide : & Slide , timestamp : u64 , config : & Config ) -> String {
28+ let image_path = crate :: path:: image_path ( out_dir, slide) ;
29+ let image_file = image_path. file_name ( ) . unwrap ( ) ;
30+ let image_file = add_timestamp ( image_file, timestamp) ;
31+ let audio_ext = config. audio_format . as_ref ( ) . unwrap ( ) ;
32+ let audio_path = crate :: path:: audio_path ( out_dir, slide, audio_ext) ;
33+ let audio_file = audio_path. file_name ( ) . unwrap ( ) ;
34+ let audio_file = add_timestamp ( audio_file, timestamp) ;
2735 format ! (
2836 indoc:: indoc! { "
29- <h2>Slide {}</h2>
37+ <div class='slide'>
38+ <h2>Slide {}</h2>
3039
31- <video controls>
32- <source src='{}' type='video/mp4'>
33- Your browser does not support the video tag.
34- </video>
40+ <a href='{}'>
41+ <img src='{}' alt='Slide {}'/><br/>
42+ </a>
43+ <audio controls src='{}'/></audio>
44+ </div>
3545 " } ,
36- slide. idx, filename
46+ slide. idx, image_file , image_file , slide . idx , audio_file
3747 )
3848}
3949
40- fn index ( args : & Arguments , slides : & [ Slide ] , timestamp : u64 , init : bool ) -> String {
50+ fn index (
51+ args : & Arguments ,
52+ config : & Config ,
53+ slides : & [ Slide ] ,
54+ timestamp : u64 ,
55+ init : bool ,
56+ ) -> String {
4157 let out_dir = & args. out_dir ;
4258 let core = slides
4359 . iter ( )
44- . map ( |slide| core_html ( out_dir, slide, timestamp) )
60+ . map ( |slide| core_html ( out_dir, slide, timestamp, config ) )
4561 . collect :: < Vec < _ > > ( )
4662 . join ( "\n " ) ;
4763 let waiting_text = if init {
@@ -65,8 +81,19 @@ fn index(args: &Arguments, slides: &[Slide], timestamp: u64, init: bool) -> Stri
6581 body {{
6682 text-align: center;
6783 }}
68- video {{
84+ img {{
6985 max-width: 800px;
86+ max-height: 80vh;
87+ border: 1px solid black;
88+ }}
89+ audio {{
90+ width: 800px;
91+ }}
92+ .slide {{
93+ margin-bottom: 60px;
94+ }}
95+ .slide h2 {{
96+ margin-bottom: 10px;
7097 }}
7198 </style>
7299 </head>
@@ -88,8 +115,8 @@ fn public_dir(args: &Arguments) -> PathBuf {
88115 public_path
89116}
90117
91- fn build_index ( args : & Arguments , slides : & [ Slide ] , timestamp : u64 , init : bool ) {
92- let index = index ( args, slides, timestamp, init) ;
118+ fn build_index ( args : & Arguments , config : & Config , slides : & [ Slide ] , timestamp : u64 , init : bool ) {
119+ let index = index ( args, config , slides, timestamp, init) ;
93120 let path = public_dir ( args) . join ( "index.html" ) ;
94121 tracing:: info!( "Writing index.html" ) ;
95122 std:: fs:: write ( path, index) . unwrap ( ) ;
@@ -105,18 +132,24 @@ fn timestamp() -> u64 {
105132 . as_secs ( )
106133}
107134
108- fn move_files_into_public ( args : & Arguments , slides : & [ Slide ] ) -> u64 {
135+ fn move_files_into_public ( args : & Arguments , config : & Config , slides : & [ Slide ] ) -> u64 {
109136 let public_path = public_dir ( args) ;
110137 let out_dir = & args. out_dir ;
111138
112139 let timestamp = timestamp ( ) ;
113140
114141 for slide in slides {
115- let video_path = crate :: path:: video_path ( out_dir, slide) ;
116- let filename = video_path . file_name ( ) . unwrap ( ) ;
142+ let image_path = crate :: path:: image_path ( out_dir, slide) ;
143+ let filename = image_path . file_name ( ) . unwrap ( ) ;
117144 let filename = add_timestamp ( filename, timestamp) ;
118145
119- std:: fs:: copy ( video_path, public_path. join ( filename) ) . unwrap ( ) ;
146+ std:: fs:: copy ( image_path, public_path. join ( filename) ) . unwrap ( ) ;
147+
148+ let audio_ext = config. audio_format . clone ( ) . unwrap ( ) ;
149+ let audio_path = crate :: path:: audio_path ( out_dir, slide, & audio_ext) ;
150+ let filename = audio_path. file_name ( ) . unwrap ( ) ;
151+ let filename = add_timestamp ( filename, timestamp) ;
152+ std:: fs:: copy ( audio_path, public_path. join ( filename) ) . unwrap ( ) ;
120153 }
121154 timestamp
122155}
@@ -130,7 +163,7 @@ fn remove_old_files(args: &Arguments, timestamp: u64) {
130163 continue ;
131164 }
132165 if let Some ( extension) = path. extension ( ) {
133- if extension == "mp4 " {
166+ if extension != "html " {
134167 let filename = path. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
135168 if !filename. contains ( & format ! ( "_{}" , timestamp) ) {
136169 std:: fs:: remove_file ( path) . unwrap ( ) ;
@@ -169,16 +202,16 @@ fn run_pre_typst(watch_args: &WatchArgs) -> Status {
169202 Status :: Success
170203}
171204
172- async fn watch_build ( watch_args : & WatchArgs , args : & Arguments ) {
205+ async fn watch_build ( watch_args : & WatchArgs , config : & Config , args : & Arguments ) {
173206 let release = false ;
174207 let input = watch_args. input . clone ( ) ;
175208 let audio_codec = None ;
176209
177210 let status = run_pre_typst ( watch_args) ;
178211 if status == Status :: Success {
179- let slides = build ( input. clone ( ) , args, release, audio_codec) . await ;
180- let timestamp = move_files_into_public ( args, & slides) ;
181- build_index ( args, & slides, timestamp, false ) ;
212+ let slides = build ( input. clone ( ) , config , args, release, audio_codec) . await ;
213+ let timestamp = move_files_into_public ( args, config , & slides) ;
214+ build_index ( args, config , & slides, timestamp, false ) ;
182215 remove_old_files ( args, timestamp) ;
183216 }
184217}
@@ -203,7 +236,7 @@ fn spawn_server(watch_args: &WatchArgs, args: &Arguments) {
203236 } ) ;
204237}
205238
206- pub async fn watch ( watch_args : & WatchArgs , args : & Arguments ) {
239+ pub async fn watch ( watch_args : & WatchArgs , config : & Config , args : & Arguments ) {
207240 let ( tx, rx) = mpsc:: channel :: < Result < Event > > ( ) ;
208241 let mut watcher = recommended_watcher ( tx) . unwrap ( ) ;
209242 let mode = notify:: RecursiveMode :: NonRecursive ;
@@ -228,14 +261,14 @@ pub async fn watch(watch_args: &WatchArgs, args: &Arguments) {
228261
229262 let slides = [ ] ;
230263 let timestamp = timestamp ( ) ;
231- build_index ( args, & slides, timestamp, true ) ;
264+ build_index ( args, config , & slides, timestamp, true ) ;
232265 spawn_server ( watch_args, args) ;
233- watch_build ( watch_args, args) . await ;
266+ watch_build ( watch_args, config , args) . await ;
234267
235268 for result in & rx {
236269 match result {
237270 Ok ( _event) => {
238- watch_build ( watch_args, args) . await ;
271+ watch_build ( watch_args, config , args) . await ;
239272 // Drain the channel to avoid processing old events.
240273 while rx. try_recv ( ) . is_ok ( ) { }
241274 }
0 commit comments