1use anyhow::Result;
4use log::debug;
5use std::io::Read;
6use std::path::Path;
7
8pub const HMR_CLIENT_SCRIPT: &str = include_str!("hmr_client.js");
10
11pub fn is_html_file(path: &Path) -> bool {
13 if let Some(ext) = path.extension() {
14 ext.to_string_lossy().eq_ignore_ascii_case("html")
15 } else {
16 false
17 }
18}
19
20pub fn inject_hmr_client(html_content: &str, _port: u16) -> Result<String> {
22 debug!("Injecting HMR client code into HTML response");
23
24 if html_content.contains("__ORBIT_REGISTER_HMR_HANDLER") {
26 debug!("HMR client code already present in HTML");
27 return Ok(html_content.to_owned());
28 }
29
30 if let Some(pos) = html_content.to_lowercase().rfind("</body>") {
32 let (before, after) = html_content.split_at(pos);
33
34 let script = format!(
37 "<script type=\"text/javascript\" src=\"/__orbit_hmr_client.js?v={}\"></script>\n",
38 std::time::SystemTime::now()
39 .duration_since(std::time::UNIX_EPOCH)
40 .unwrap_or_default()
41 .as_secs()
42 );
43
44 let injected_html = format!("{before}{script}{after}");
46 debug!("HMR client code injected successfully");
47
48 Ok(injected_html)
49 } else {
50 debug!("No </body> tag found, appending HMR client code at the end");
52 let script = format!(
53 "<script type=\"text/javascript\" src=\"/__orbit_hmr_client.js?v={}\"></script>\n",
54 std::time::SystemTime::now()
55 .duration_since(std::time::UNIX_EPOCH)
56 .unwrap_or_default()
57 .as_secs()
58 );
59 let injected_html = format!("{html_content}{script}");
60
61 Ok(injected_html)
62 }
63}
64
65pub fn get_hmr_client_js() -> &'static str {
67 HMR_CLIENT_SCRIPT
68}
69
70pub fn process_html_file(path: &Path, port: u16) -> Result<Vec<u8>> {
72 debug!("Processing HTML file: {path:?}");
73
74 let mut file = std::fs::File::open(path)?;
76 let mut content = String::new();
77 file.read_to_string(&mut content)?;
78
79 let injected_content = inject_hmr_client(&content, port)?;
81
82 Ok(injected_content.into_bytes())
83}