arc_web/helpers/
template.rs1use once_cell::sync::Lazy;
2use std::collections::HashMap;
3use std::fs;
4use std::io::Error;
5use tera::{Context, Tera};
6use tracing::error;
7
8static TEMPLATES: Lazy<Tera> = Lazy::new(|| {
10 let patterns = vec![
12 "crates/arc-app/src/resources/views/**/*", "src/resources/views/**/*", ];
15
16 for pattern in patterns {
17 match Tera::new(pattern) {
20 Ok(t) if t.get_template_names().next().is_some() => return t,
21 _ => continue,
22 }
23 }
24
25 error!("Fatal error: Could not find templates in any expected location");
26 ::std::process::exit(1);
27});
28
29static MANIFEST_ASSETS: Lazy<HashMap<String, String>> = Lazy::new(parse_manifest_assets);
31
32pub fn load_template(
35 template: &str,
36 params: Vec<(&str, &str)>,
37 assets: Option<Vec<&str>>,
38) -> String {
39 let mut context: Context = Context::new();
40 for (key, value) in params.into_iter() {
41 context.insert(key, value);
42 }
43
44 if !context.contains_key("session_message") {
45 context.insert("session_message", "");
46 }
47
48 context.insert("assets", &get_assets_string(assets));
49
50 TEMPLATES
51 .render(template, &context)
52 .expect("Failed to render template")
53}
54
55fn get_assets_string(assets: Option<Vec<&str>>) -> String {
59 let mut assets_string: String = String::new();
60 if let Some(assets) = assets {
61 for value in assets.into_iter() {
62 let asset_type = value.split('.').next_back().unwrap();
63 if let Some(asset) = MANIFEST_ASSETS.get(value) {
64 if asset_type == "css" {
65 assets_string.push_str(&format!(
66 "<link rel=\"stylesheet\" href=\"/public/{}\">",
67 asset
68 ));
69 } else if asset_type == "js" {
70 assets_string.push_str(&format!(
71 "<script src=\"/public/{}\" defer></script>",
72 asset
73 ));
74 }
75 }
76 }
77 } else {
78 for value in MANIFEST_ASSETS.values() {
79 let asset_type = value.split('.').next_back().unwrap();
80 if asset_type == "css" {
81 assets_string.push_str(&format!(
82 "<link rel=\"stylesheet\" href=\"/public/{}\">",
83 value
84 ));
85 } else if asset_type == "js" {
86 assets_string.push_str(&format!(
87 "<script src=\"/public/{}\" defer></script>",
88 value
89 ));
90 }
91 }
92 }
93
94 assets_string
95}
96
97fn parse_manifest_assets() -> HashMap<String, String> {
99 let mut assets: HashMap<String, String> = HashMap::new();
100 let manifest: Result<String, Error> = fs::read_to_string("dist/.vite/manifest.json");
101 if let Ok(manifest) = manifest {
102 let manifest_json: serde_json::Value =
103 serde_json::from_str(&manifest).expect("Failed to parse manifest.json");
104
105 for (key, value) in manifest_json.as_object().unwrap().iter() {
106 if let Some(asset) = value.get("file") {
107 assets.insert(key.to_string(), asset.as_str().unwrap().parse().unwrap());
108
109 let asset_type = asset.as_str().unwrap().split('.').next_back().unwrap();
111 if asset_type == "js" {
112 if let Some(css_array) = value.get("css").and_then(|v| v.as_array()) {
113 for css_file in css_array {
114 let css_file_name =
115 css_file.as_str().unwrap().split('/').next_back().unwrap();
116 assets.insert(css_file_name.to_string(), css_file_name.to_string());
117 }
118 }
119 }
120 }
121 }
122 }
123
124 assets
125}