rustolio_build_utils/
lib.rs1mod fs;
12mod paths;
13mod tailwind;
14
15use std::env;
16
17pub use rustolio_utils::{prelude::*, Error, Result};
18
19pub fn handle_lib() -> Result<()> {
20 if !is_wasm_build()? {
21 return Ok(());
22 }
23 tailwind::push_info()?;
24 fs::copy(
25 &paths::static_dir()?,
26 &paths::web_build_dir()?.join(cargo_pkg_name()?),
27 )?;
28 Ok(())
29}
30
31pub fn handle_bin() -> Result<()> {
32 if !is_wasm_build()? {
33 return Ok(());
34 }
35 force_rebuild()?; create_default_static_files()?;
37 tailwind::execute()?;
38 fs::copy(&paths::web_build_dir()?, &paths::pkg_dir()?)?;
39 fs::copy(&paths::static_dir()?, &paths::pkg_dir()?)?;
40 Ok(())
41}
42
43fn create_default_static_files() -> Result<()> {
44 let static_dir = paths::static_dir()?;
45
46 let index_html = default_index_html()?;
47 fs::create(&static_dir.join("index.html"), &index_html)?;
48
49 Ok(())
50}
51
52fn default_index_html() -> Result<String> {
53 const INDEX_CONTENT: &str = r#"
54<!DOCTYPE html>
55<html lang="en-US">
56 <head>
57 <meta charset="utf-8" />
58 <title>{PRETTY_PKG_NAME}</title>
59 {LINKS}
60 </head>
61 <body>
62 <div id="root"></div>
63 <script type="module">
64 import init, { entry } from "/./{PKG_NAME}.js"
65 init().then(() => {
66 entry()
67 })
68 </script>
69 </body>
70</html>
71"#;
72 const TAILWIND_LINK: &str = r#"<link rel="stylesheet" href="/./tailwind.css" />"#;
73
74 let mut links = Vec::new();
75 if tailwind::enabled()? {
76 links.push(TAILWIND_LINK.to_string());
77 }
78 let links = links.join("\n ");
79
80 Ok(INDEX_CONTENT
81 .replace("{LINKS}", &links)
82 .replace("{PRETTY_PKG_NAME}", &pretty_pkg_name()?)
83 .replace("{PKG_NAME}", &cargo_pkg_name()?.replace("-", "_")))
84}
85
86fn is_wasm_build() -> Result<bool> {
87 Ok(env::var("CARGO_CFG_TARGET_ARCH").context("CARGO_CFG_TARGET_ARCH not set")? == "wasm32")
88}
89
90fn pretty_pkg_name() -> Result<String> {
92 Ok(cargo_pkg_name()?
93 .replace("_", " ")
94 .replace("-", " ")
95 .split(' ')
96 .map(|s| {
97 let mut c = s.chars();
98 match c.next() {
99 None => String::new(),
100 Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
101 }
102 })
103 .collect::<Vec<_>>()
104 .join(" "))
105}
106
107fn cargo_pkg_name() -> Result<String> {
108 env::var("CARGO_PKG_NAME").context("CARGO_PKG_NAME not set")
109}
110
111fn force_rebuild() -> Result<()> {
112 let dummy_timestamp = paths::out_dir()?.join("dummy.timestamp");
113
114 println!(
116 "cargo:rerun-if-changed={}",
117 dummy_timestamp
118 .to_str()
119 .context("Failed to convert to str")?
120 );
121
122 let timestamp = std::time::SystemTime::now()
124 .duration_since(std::time::UNIX_EPOCH)
125 .unwrap()
126 .as_secs();
127 std::fs::write(dummy_timestamp, timestamp.to_string()).context("Failed to write dummy file")?;
128 Ok(())
129}