Skip to main content

tinted_builder/
template.rs

1mod base16;
2mod tinted8;
3
4use crate::{error::TintedBuilderError, scheme::Scheme};
5
6/// A struct representing a template that can be rendered with the provided color scheme.
7///
8/// The `Template` struct holds the content of the template and the scheme used to render it. It
9/// provides methods to create a new template and render it into a `String` using the specified
10/// color scheme.
11pub struct Template {
12    content: String,
13    scheme: Scheme,
14}
15
16impl Template {
17    /// Creates a new `Template` instance.
18    ///
19    /// # Arguments
20    ///
21    /// * `content` - A `String` representing the content of the template.
22    /// * `scheme` - A `Scheme` enum that determines which color scheme to use when rendering the template.
23    ///
24    /// # Returns
25    ///
26    /// A new `Template` instance with the provided content and scheme.
27    #[must_use]
28    pub const fn new(content: String, scheme: Scheme) -> Self {
29        Self { content, scheme }
30    }
31
32    /// Renders the template into a `String` using the provided color scheme.
33    ///
34    /// This method applies the specified `Scheme` to the template content, converting placeholders
35    /// in the content to their corresponding values from the scheme context.
36    ///
37    /// # Errors
38    ///
39    /// Returns a `TintedBuilderError` if the rendering process fails. This could happen if the
40    /// content contains placeholders that cannot be resolved using the scheme context.
41    ///
42    /// # Examples
43    ///
44    /// ```
45    /// use tinted_builder::{Template, Scheme};
46    ///
47    /// let scheme_yaml = r#"
48    /// system: "base16"
49    /// name: "Some name"
50    /// author: "Some author"
51    /// variant: "dark"
52    /// palette:
53    ///   base00: "241b26"
54    ///   base01: "2f2a3f"
55    ///   base02: "46354a"
56    ///   base03: "6c3cb2"
57    ///   base04: "7e5f83"
58    ///   base05: "eed5d9"
59    ///   base06: "d9c2c6"
60    ///   base07: "e4ccd0"
61    ///   base08: "877bb6"
62    ///   base09: "de5b44"
63    ///   base0A: "a84a73"
64    ///   base0B: "c965bf"
65    ///   base0C: "9c5fce"
66    ///   base0D: "6a9eb5"
67    ///   base0E: "78a38f"
68    ///   base0F: "a3a079"
69    /// "#;
70    /// let template = Template::new(
71    ///     r#"{{scheme-system}} scheme name is "{{scheme-name}}" and first color is #{{base00-hex}}"#.to_string(),
72    ///     Scheme::from_yaml(scheme_yaml).unwrap()
73    /// );
74    /// let rendered = template.render().unwrap();
75    ///
76    /// assert_eq!(
77    ///     rendered,
78    ///     r#"base16 scheme name is "Some name" and first color is #241b26"#
79    /// );
80    /// ```
81    pub fn render(&self) -> Result<String, TintedBuilderError> {
82        match self.scheme {
83            Scheme::Base16(ref scheme) => {
84                let ctx = base16::to_template_context(&scheme.into());
85                let rendered = base16::render(&self.content, &ctx)?;
86                Ok(rendered)
87            }
88            Scheme::Base24(ref scheme) => {
89                let ctx = base16::to_template_context(&scheme.into());
90                let rendered = base16::render(&self.content, &ctx)?;
91                Ok(rendered)
92            }
93            Scheme::Tinted8(ref scheme) => {
94                let ctx = tinted8::to_template_context(scheme)?;
95                let rendered = tinted8::render(&self.content, &ctx)?;
96                Ok(rendered)
97            }
98        }
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use crate::{Scheme, Template};
105
106    const SCHEME: &str = r##"
107system: "base16"
108name: "Test"
109slug: "test"
110author: "Me"
111variant: "dark"
112palette:
113  base00: "#000000"
114  base01: "#111111"
115  base02: "#222222"
116  base03: "#333333"
117  base04: "#444444"
118  base05: "#555555"
119  base06: "#666666"
120  base07: "#777777"
121  base08: "#888888"
122  base09: "#999999"
123  base0A: "#aaaaaa"
124  base0B: "#bbbbbb"
125  base0C: "#cccccc"
126  base0D: "#dddddd"
127  base0E: "#eeeeee"
128  base0F: "#ffffff"
129"##;
130
131    #[test]
132    fn renders_plain_text() {
133        #[allow(clippy::unwrap_used)]
134        let tpl = Template::new(
135            "Hello".to_string(),
136            Scheme::Base16(serde_yaml::from_str(SCHEME).unwrap()),
137        );
138        assert_eq!(tpl.render().expect("unable to render"), "Hello");
139    }
140
141    #[test]
142    fn renders_base16_variable_hex() {
143        #[allow(clippy::unwrap_used)]
144        let tpl = Template::new(
145            "#{{base0A-hex}}".to_string(),
146            Scheme::Base16(serde_yaml::from_str(SCHEME).unwrap()),
147        );
148        assert_eq!(tpl.render().expect("unable to render"), "#aaaaaa");
149    }
150}