weaver_lib/
config.rs

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        // Remove any trailing slash.
138        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}