Skip to main content

modo/template/
config.rs

1use serde::Deserialize;
2
3/// Configuration for the template engine.
4///
5/// All fields have sensible defaults and can be overridden via YAML config.
6/// Paths are relative to the working directory of the running process.
7///
8/// # Defaults
9///
10/// | Field                | Default         |
11/// |----------------------|-----------------|
12/// | `templates_path`     | `"templates"`   |
13/// | `static_path`        | `"static"`      |
14/// | `static_url_prefix`  | `"/assets"`     |
15/// | `locales_path`       | `"locales"`     |
16/// | `default_locale`     | `"en"`          |
17/// | `locale_cookie`      | `"lang"`        |
18/// | `locale_query_param` | `"lang"`        |
19#[non_exhaustive]
20#[derive(Debug, Clone, Deserialize)]
21#[serde(default)]
22pub struct TemplateConfig {
23    /// Directory that contains MiniJinja template files.
24    pub templates_path: String,
25    /// Directory that contains static assets (CSS, JS, images, etc.).
26    pub static_path: String,
27    /// URL prefix under which static assets are served (e.g. `"/assets"`).
28    pub static_url_prefix: String,
29    /// Directory that contains locale subdirectories with YAML translation files.
30    pub locales_path: String,
31    /// BCP 47 language tag used when no locale can be resolved from the request.
32    pub default_locale: String,
33    /// Cookie name read by [`CookieResolver`](super::CookieResolver) to determine the active locale.
34    pub locale_cookie: String,
35    /// Query-string parameter name read by [`QueryParamResolver`](super::QueryParamResolver).
36    pub locale_query_param: String,
37}
38
39impl Default for TemplateConfig {
40    fn default() -> Self {
41        Self {
42            templates_path: "templates".into(),
43            static_path: "static".into(),
44            static_url_prefix: "/assets".into(),
45            locales_path: "locales".into(),
46            default_locale: "en".into(),
47            locale_cookie: "lang".into(),
48            locale_query_param: "lang".into(),
49        }
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn default_config_has_sensible_values() {
59        let config = TemplateConfig::default();
60        assert_eq!(config.templates_path, "templates");
61        assert_eq!(config.static_path, "static");
62        assert_eq!(config.static_url_prefix, "/assets");
63        assert_eq!(config.locales_path, "locales");
64        assert_eq!(config.default_locale, "en");
65        assert_eq!(config.locale_cookie, "lang");
66        assert_eq!(config.locale_query_param, "lang");
67    }
68
69    #[test]
70    fn config_deserializes_from_yaml() {
71        let yaml = r#"
72            templates_path: "views"
73            static_path: "public"
74            static_url_prefix: "/static"
75            locales_path: "i18n"
76            default_locale: "uk"
77            locale_cookie: "locale"
78            locale_query_param: "locale"
79        "#;
80        let config: TemplateConfig = serde_yaml_ng::from_str(yaml).unwrap();
81        assert_eq!(config.templates_path, "views");
82        assert_eq!(config.static_path, "public");
83        assert_eq!(config.static_url_prefix, "/static");
84        assert_eq!(config.locales_path, "i18n");
85        assert_eq!(config.default_locale, "uk");
86        assert_eq!(config.locale_cookie, "locale");
87        assert_eq!(config.locale_query_param, "locale");
88    }
89
90    #[test]
91    fn config_uses_defaults_for_missing_fields() {
92        let yaml = r#"
93            templates_path: "views"
94        "#;
95        let config: TemplateConfig = serde_yaml_ng::from_str(yaml).unwrap();
96        assert_eq!(config.templates_path, "views");
97        assert_eq!(config.static_path, "static");
98        assert_eq!(config.default_locale, "en");
99    }
100}