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 ServeConfig {
27 pub watch_excludes: Vec<String>,
28 pub address: String,
29 pub npm_build: bool,
30}
31
32impl Default for ServeConfig {
33 fn default() -> Self {
34 Self {
35 watch_excludes: vec![".git".into(), "node_modules".into(), "site".into()],
36 address: "localhost:8080".into(),
37 npm_build: false,
38 }
39 }
40}
41
42#[derive(Serialize, Deserialize, Debug)]
43#[serde(default)]
44pub struct WeaverConfig {
45 pub version: String,
46 pub base_dir: String,
47 pub content_dir: String,
48 pub base_url: String,
49 pub partials_dir: String,
50 pub public_dir: String,
51 pub template_dir: String,
52 pub build_dir: String,
53 pub templating_language: TemplateLang,
54 pub image_config: ImageConfig,
55 pub serve_config: ServeConfig,
56}
57
58impl Default for WeaverConfig {
59 fn default() -> Self {
60 let base_path = std::env::var_os("WEAVING_BASE_PATH")
61 .unwrap_or(std::env::current_dir().unwrap().as_os_str().to_os_string())
62 .to_str()
63 .unwrap()
64 .to_string();
65
66 Self {
67 version: "1".into(),
68 base_dir: base_path.clone(),
69 content_dir: "content".into(),
70 base_url: "localhost:8080".into(),
71 partials_dir: "partials".into(),
72 public_dir: "public".into(),
73 build_dir: "site".into(),
74 template_dir: "templates".into(),
75 templating_language: TemplateLang::Liquid,
76 image_config: Default::default(),
77 serve_config: Default::default(),
78 }
79 }
80}
81
82impl WeaverConfig {
83 pub fn new() -> Self {
84 let inst = Self::default();
85
86 let config_file_result = std::fs::read_to_string(format!("{}/weaving.toml", inst.base_dir));
87
88 if config_file_result.is_err() {
89 return Self {
90 version: "1".into(),
91 base_dir: inst.base_dir.clone(),
92 content_dir: format!("{}/{}", &inst.base_dir, inst.content_dir),
93 template_dir: format!("{}/{}", &inst.base_dir, inst.template_dir),
94 base_url: inst.base_url,
95 partials_dir: format!("{}/{}", &inst.base_dir, inst.partials_dir),
96 public_dir: format!("{}/{}", &inst.base_dir, inst.public_dir),
97 build_dir: format!("{}/{}", &inst.base_dir, inst.build_dir),
98 templating_language: TemplateLang::Liquid,
99 image_config: inst.image_config,
100 serve_config: inst.serve_config,
101 };
102 }
103 let user_supplied_config: WeaverConfig =
104 toml::from_str(config_file_result.unwrap().as_str()).unwrap();
105
106 Self {
107 version: user_supplied_config.version,
108 base_dir: user_supplied_config.base_dir.clone(),
109 content_dir: format!(
110 "{}/{}",
111 &user_supplied_config.base_dir, user_supplied_config.content_dir
112 ),
113 base_url: user_supplied_config.base_url,
114 partials_dir: format!(
115 "{}/{}",
116 &user_supplied_config.base_dir, user_supplied_config.partials_dir
117 ),
118 public_dir: format!(
119 "{}/{}",
120 &user_supplied_config.base_dir, user_supplied_config.public_dir
121 ),
122 build_dir: format!(
123 "{}/{}",
124 &user_supplied_config.base_dir, user_supplied_config.build_dir
125 ),
126 template_dir: format!(
127 "{}/{}",
128 &user_supplied_config.base_dir, user_supplied_config.template_dir
129 ),
130 templating_language: user_supplied_config.templating_language,
131 image_config: user_supplied_config.image_config,
132 serve_config: user_supplied_config.serve_config,
133 }
134 }
135
136 pub fn new_from_path(base_path: PathBuf) -> Self {
137 let safe_path = base_path.to_str().unwrap();
139 let config_file_result = std::fs::read_to_string(format!("{}/weaving.toml", safe_path));
140
141 if config_file_result.is_err() {
142 return Self::new();
143 }
144
145 let user_supplied_config: WeaverConfig =
146 toml::from_str(config_file_result.unwrap().as_str()).unwrap();
147
148 Self {
149 version: user_supplied_config.version,
150 base_dir: safe_path.to_string(),
151 content_dir: format!("{}/{}", &safe_path, user_supplied_config.content_dir),
152 base_url: user_supplied_config.base_url,
153 partials_dir: format!("{}/{}", &safe_path, user_supplied_config.partials_dir),
154 public_dir: format!("{}/{}", &safe_path, user_supplied_config.public_dir),
155 build_dir: format!("{}/{}", &safe_path, user_supplied_config.build_dir),
156 template_dir: format!("{}/{}", &safe_path, user_supplied_config.template_dir),
157 templating_language: user_supplied_config.templating_language,
158 image_config: user_supplied_config.image_config,
159 serve_config: user_supplied_config.serve_config,
160 }
161 }
162}
163
164#[cfg(test)]
165mod test {
166 use super::*;
167 use pretty_assertions::assert_eq;
168
169 #[test]
170 fn test_defaultyness() {
171 let base_path = std::env::current_dir()
172 .unwrap()
173 .as_os_str()
174 .to_os_string()
175 .to_str()
176 .unwrap()
177 .to_string();
178 let config = WeaverConfig::new();
179
180 assert_eq!(config.base_dir, base_path);
181 assert_eq!(config.content_dir, format!("{}/content", base_path));
182 assert_eq!(config.partials_dir, format!("{}/partials", base_path));
183 assert_eq!(config.public_dir, format!("{}/public", base_path));
184 assert_eq!(config.build_dir, format!("{}/site", base_path));
185 assert_eq!(config.base_url, "localhost:8080");
186 }
187
188 #[test]
189 fn test_with_empty_config_file() {
190 let base_path_wd = std::env::current_dir()
191 .unwrap()
192 .as_os_str()
193 .to_os_string()
194 .to_str()
195 .unwrap()
196 .to_string();
197 let base_path = format!("{}/test_fixtures/config/empty_config", base_path_wd);
198 let config = WeaverConfig::new_from_path(base_path.clone().into());
199
200 assert_eq!(config.base_dir, base_path);
201 assert_eq!(config.content_dir, format!("{}/content", base_path));
202 assert_eq!(config.partials_dir, format!("{}/partials", base_path));
203 assert_eq!(config.public_dir, format!("{}/public", base_path));
204 assert_eq!(config.build_dir, format!("{}/site", base_path));
205 assert_eq!(config.base_url, "localhost:8080");
206 }
207
208 #[test]
209 fn test_with_filled_config_file() {
210 let base_path_wd = std::env::current_dir().unwrap().display().to_string();
211 let base_path = format!("{}/test_fixtures/config/full_config", base_path_wd);
212 let config = WeaverConfig::new_from_path(base_path.clone().into());
213
214 assert_eq!(config.base_dir, base_path);
215 assert_eq!(config.content_dir, format!("{}/content", base_path));
216 assert_eq!(config.partials_dir, format!("{}/partials", base_path));
217 assert_eq!(config.public_dir, format!("{}/static", base_path));
218 assert_eq!(config.build_dir, format!("{}/site", base_path));
219 assert_eq!(config.base_url, "localhost:9090");
220 assert_eq!(config.image_config.quality, 100);
221 assert_eq!(config.serve_config.npm_build, true);
222 assert_eq!(config.serve_config.address, "localhost:3030");
223 }
224
225 #[test]
226 fn test_with_partial_config_file() {
227 let base_path_wd = std::env::current_dir().unwrap().display().to_string();
228 let base_path = format!("{}/test_fixtures/config/partial_config", base_path_wd);
229 let config = WeaverConfig::new_from_path(base_path.clone().into());
230
231 assert_eq!(config.base_dir, base_path);
232 assert_eq!(config.content_dir, format!("{}/content", base_path));
233 assert_eq!(config.partials_dir, format!("{}/partials", base_path));
234 assert_eq!(config.public_dir, format!("{}/static", base_path));
235 assert_eq!(config.build_dir, format!("{}/site", base_path));
236 assert_eq!(config.base_url, "localhost:8080");
237 }
238}