1use std::path::PathBuf;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Serialize, Deserialize, Debug, PartialEq, Default)]
6#[serde(rename_all = "lowercase")]
7pub enum TemplateLang {
8 #[default]
9 Liquid,
10}
11
12#[derive(Serialize, Deserialize, PartialEq, 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, PartialEq, 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, PartialEq, 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 pub syntax_theme: String,
57}
58
59impl Default for WeaverConfig {
60 fn default() -> Self {
61 let base_path = std::env::var_os("WEAVING_BASE_PATH")
62 .unwrap_or(std::env::current_dir().unwrap().as_os_str().to_os_string())
63 .to_str()
64 .unwrap()
65 .to_string();
66
67 let base_url = std::env::var_os("WEAVING_BASE_URL")
68 .unwrap_or("http://localhost:8080".into())
69 .to_str()
70 .unwrap()
71 .to_string();
72
73 Self {
74 version: "1".into(),
75 base_dir: base_path.clone(),
76 content_dir: "content".into(),
77 base_url,
78 partials_dir: "partials".into(),
79 public_dir: "public".into(),
80 build_dir: "site".into(),
81 template_dir: "templates".into(),
82 templating_language: TemplateLang::Liquid,
83 image_config: Default::default(),
84 serve_config: Default::default(),
85 syntax_theme: "base16-ocean.dark".into(),
86 }
87 }
88}
89impl WeaverConfig {
90 pub fn new(base_dir: PathBuf) -> Self {
91 let base_dir_str = base_dir.display().to_string();
92
93 let config_file_result = std::fs::read_to_string(format!("{}/weaving.toml", base_dir_str));
94
95 let user_supplied_config: WeaverConfig = if let Ok(config_file) = config_file_result {
96 toml::from_str(config_file.as_str()).unwrap()
97 } else {
98 Self {
99 base_dir: base_dir_str.clone(),
100 ..Default::default()
101 }
102 };
103
104 Self {
105 base_dir: base_dir_str.clone(),
106 content_dir: format!("{}/{}", &base_dir_str, user_supplied_config.content_dir),
107 partials_dir: format!("{}/{}", &base_dir_str, user_supplied_config.partials_dir),
108 public_dir: format!("{}/{}", &base_dir_str, user_supplied_config.public_dir),
109 build_dir: format!("{}/{}", &base_dir_str, user_supplied_config.build_dir),
110 template_dir: format!("{}/{}", &base_dir_str, user_supplied_config.template_dir),
111 ..user_supplied_config
112 }
113 }
114}
115
116#[cfg(test)]
117mod test {
118 use super::*;
119 use pretty_assertions::assert_eq;
120
121 #[test]
122 fn test_defaultyness() {
123 let base_path = std::env::current_dir()
124 .unwrap()
125 .as_os_str()
126 .to_os_string()
127 .to_str()
128 .unwrap()
129 .to_string();
130 let config = WeaverConfig::new(base_path.clone().into());
131
132 assert_eq!(config.base_dir, base_path);
133 assert_eq!(config.content_dir, format!("{}/content", base_path));
134 assert_eq!(config.partials_dir, format!("{}/partials", base_path));
135 assert_eq!(config.public_dir, format!("{}/public", base_path));
136 assert_eq!(config.build_dir, format!("{}/site", base_path));
137 assert_eq!(config.base_url, "http://localhost:8080");
138 }
139
140 #[test]
141 fn test_with_empty_config_file() {
142 let base_path_wd = std::env::current_dir()
143 .unwrap()
144 .as_os_str()
145 .to_os_string()
146 .to_str()
147 .unwrap()
148 .to_string();
149 let base_path = format!("{}/test_fixtures/config/empty_config", base_path_wd);
150 let config = WeaverConfig::new(base_path.clone().into());
151
152 assert_eq!(config.base_dir, base_path);
153 assert_eq!(config.content_dir, format!("{}/content", base_path));
154 assert_eq!(config.partials_dir, format!("{}/partials", base_path));
155 assert_eq!(config.public_dir, format!("{}/public", base_path));
156 assert_eq!(config.build_dir, format!("{}/site", base_path));
157 assert_eq!(config.base_url, "http://localhost:8080");
158 }
159
160 #[test]
161 fn test_with_filled_config_file() {
162 let base_path_wd = std::env::current_dir().unwrap().display().to_string();
163 let base_path = format!("{}/test_fixtures/config/full_config", base_path_wd);
164 let config = WeaverConfig::new(base_path.clone().into());
165
166 assert_eq!(config.base_dir, base_path);
167 assert_eq!(config.content_dir, format!("{}/content", base_path));
168 assert_eq!(config.partials_dir, format!("{}/partials", base_path));
169 assert_eq!(config.public_dir, format!("{}/static", base_path));
170 assert_eq!(config.build_dir, format!("{}/site", base_path));
171 assert_eq!(config.base_url, "localhost:9090");
172 assert_eq!(config.image_config.quality, 100);
173 assert_eq!(config.serve_config.npm_build, true);
174 assert_eq!(config.serve_config.address, "localhost:3030");
175 }
176
177 #[test]
178 fn test_with_partial_config_file() {
179 let base_path_wd = std::env::current_dir().unwrap().display().to_string();
180 let base_path = format!("{}/test_fixtures/config/partial_config", base_path_wd);
181 let config = WeaverConfig::new(base_path.clone().into());
182
183 assert_eq!(config.base_dir, base_path);
184 assert_eq!(config.content_dir, format!("{}/content", base_path));
185 assert_eq!(config.partials_dir, format!("{}/partials", base_path));
186 assert_eq!(config.public_dir, format!("{}/static", base_path));
187 assert_eq!(config.build_dir, format!("{}/site", base_path));
188 assert_eq!(config.base_url, "http://localhost:8080");
189 }
190}