1use std::path::PathBuf;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Serialize, Deserialize, Debug, Default)]
6#[serde(rename_all = "lowercase")]
7pub enum TemplateLang {
8 #[default]
9 Liquid,
10}
11
12#[derive(Serialize, Deserialize, Debug)]
13#[serde(default)]
14pub struct ImageConfig {
15 pub quality: u8,
16}
17
18impl Default for ImageConfig {
19 fn default() -> Self {
20 Self { quality: 83 }
21 }
22}
23
24#[derive(Serialize, Deserialize, Debug)]
25#[serde(default)]
26pub struct WeaverConfig {
27 pub version: String,
28 pub base_dir: String,
29 pub content_dir: String,
30 pub base_url: String,
31 pub includes_dir: String,
32 pub public_dir: String,
33 pub template_dir: String,
34 pub build_dir: String,
35 pub templating_language: TemplateLang,
36 pub image_config: ImageConfig,
37}
38
39impl Default for WeaverConfig {
40 fn default() -> Self {
41 let base_path = std::env::var_os("WEAVING_BASE_PATH")
42 .unwrap_or(std::env::current_dir().unwrap().as_os_str().to_os_string())
43 .to_str()
44 .unwrap()
45 .to_string();
46
47 Self {
48 version: "1".into(),
49 base_dir: base_path.clone(),
50 content_dir: "content".into(),
51 base_url: "localhost:8080".into(),
52 includes_dir: "includes".into(),
53 public_dir: "public".into(),
54 build_dir: "site".into(),
55 template_dir: "templates".into(),
56 templating_language: TemplateLang::Liquid,
57 image_config: Default::default(),
58 }
59 }
60}
61
62impl WeaverConfig {
63 pub fn new() -> Self {
64 let inst = Self::default();
65
66 let config_file_result = std::fs::read_to_string(format!("{}/weaving.toml", inst.base_dir));
67
68 if config_file_result.is_err() {
69 return Self {
70 version: "1".into(),
71 base_dir: inst.base_dir.clone(),
72 content_dir: format!("{}/{}", &inst.base_dir, inst.content_dir),
73 template_dir: format!("{}/{}", &inst.base_dir, inst.template_dir),
74 base_url: inst.base_url,
75 includes_dir: format!("{}/{}", &inst.base_dir, inst.includes_dir),
76 public_dir: format!("{}/{}", &inst.base_dir, inst.public_dir),
77 build_dir: format!("{}/{}", &inst.base_dir, inst.build_dir),
78 templating_language: TemplateLang::Liquid,
79 image_config: inst.image_config,
80 };
81 }
82 let user_supplied_config: WeaverConfig =
83 toml::from_str(config_file_result.unwrap().as_str()).unwrap();
84
85 Self {
86 version: user_supplied_config.version,
87 base_dir: user_supplied_config.base_dir.clone(),
88 content_dir: format!(
89 "{}/{}",
90 &user_supplied_config.base_dir, user_supplied_config.content_dir
91 ),
92 base_url: user_supplied_config.base_url,
93 includes_dir: format!(
94 "{}/{}",
95 &user_supplied_config.base_dir, user_supplied_config.includes_dir
96 ),
97 public_dir: format!(
98 "{}/{}",
99 &user_supplied_config.base_dir, user_supplied_config.public_dir
100 ),
101 build_dir: format!(
102 "{}/{}",
103 &user_supplied_config.base_dir, user_supplied_config.build_dir
104 ),
105 template_dir: format!(
106 "{}/{}",
107 &user_supplied_config.base_dir, user_supplied_config.template_dir
108 ),
109 templating_language: user_supplied_config.templating_language,
110 image_config: user_supplied_config.image_config,
111 }
112 }
113
114 pub fn new_from_path(base_path: PathBuf) -> Self {
115 let safe_path = base_path.to_str().unwrap();
117 let config_file_result = std::fs::read_to_string(format!("{}/weaving.toml", safe_path));
118
119 if config_file_result.is_err() {
120 return Self::new();
121 }
122
123 let user_supplied_config: WeaverConfig =
124 toml::from_str(config_file_result.unwrap().as_str()).unwrap();
125
126 Self {
127 version: user_supplied_config.version,
128 base_dir: safe_path.to_string(),
129 content_dir: format!("{}/{}", &safe_path, user_supplied_config.content_dir),
130 base_url: user_supplied_config.base_url,
131 includes_dir: format!("{}/{}", &safe_path, user_supplied_config.includes_dir),
132 public_dir: format!("{}/{}", &safe_path, user_supplied_config.public_dir),
133 build_dir: format!("{}/{}", &safe_path, user_supplied_config.build_dir),
134 template_dir: format!("{}/{}", &safe_path, user_supplied_config.template_dir),
135 templating_language: user_supplied_config.templating_language,
136 image_config: user_supplied_config.image_config,
137 }
138 }
139}
140
141#[cfg(test)]
142mod test {
143 use super::*;
144 use pretty_assertions::assert_eq;
145
146 #[test]
147 fn test_defaultyness() {
148 let base_path = std::env::current_dir()
149 .unwrap()
150 .as_os_str()
151 .to_os_string()
152 .to_str()
153 .unwrap()
154 .to_string();
155 let config = WeaverConfig::new();
156
157 assert_eq!(config.base_dir, base_path);
158 assert_eq!(config.content_dir, format!("{}/content", base_path));
159 assert_eq!(config.includes_dir, format!("{}/includes", base_path));
160 assert_eq!(config.public_dir, format!("{}/public", base_path));
161 assert_eq!(config.build_dir, format!("{}/site", base_path));
162 assert_eq!(config.base_url, "localhost:8080");
163 }
164
165 #[test]
166 fn test_with_empty_config_file() {
167 let base_path_wd = std::env::current_dir()
168 .unwrap()
169 .as_os_str()
170 .to_os_string()
171 .to_str()
172 .unwrap()
173 .to_string();
174 let base_path = format!("{}/test_fixtures/config/empty_config", base_path_wd);
175 let config = WeaverConfig::new_from_path(base_path.clone().into());
176
177 assert_eq!(config.base_dir, base_path);
178 assert_eq!(config.content_dir, format!("{}/content", base_path));
179 assert_eq!(config.includes_dir, format!("{}/includes", base_path));
180 assert_eq!(config.public_dir, format!("{}/public", base_path));
181 assert_eq!(config.build_dir, format!("{}/site", base_path));
182 assert_eq!(config.base_url, "localhost:8080");
183 }
184
185 #[test]
186 fn test_with_filled_config_file() {
187 let base_path_wd = std::env::current_dir().unwrap().display().to_string();
188 let base_path = format!("{}/test_fixtures/config/custom_config", base_path_wd);
189 let config = WeaverConfig::new_from_path(base_path.clone().into());
190
191 assert_eq!(config.base_dir, base_path);
192 assert_eq!(config.content_dir, format!("{}/content", base_path));
193 assert_eq!(config.includes_dir, format!("{}/partials", base_path));
194 assert_eq!(config.public_dir, format!("{}/static", base_path));
195 assert_eq!(config.build_dir, format!("{}/site", base_path));
196 assert_eq!(config.base_url, "localhost:9090");
197 }
198
199 #[test]
200 fn test_with_partial_config_file() {
201 let base_path_wd = std::env::current_dir().unwrap().display().to_string();
202 let base_path = format!("{}/test_fixtures/config/partial_config", base_path_wd);
203 let config = WeaverConfig::new_from_path(base_path.clone().into());
204
205 assert_eq!(config.base_dir, base_path);
206 assert_eq!(config.content_dir, format!("{}/content", base_path));
207 assert_eq!(config.includes_dir, format!("{}/partials", base_path));
208 assert_eq!(config.public_dir, format!("{}/static", base_path));
209 assert_eq!(config.build_dir, format!("{}/site", base_path));
210 assert_eq!(config.base_url, "localhost:8080");
211 }
212}