1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// builder-rust is a Tinted Theming template builder which uses color
// schemes to generate theme files.
// Copyright (C) 2024  Tinted Theming

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

use anyhow::Result;
use ramhorns::Template as RamhornsTemplate;
use std::collections::HashMap;
use std::path::Path;

use crate::utils::write_to_file;
use crate::Scheme;

pub struct Template {
    content: String,
}

impl Template {
    pub fn new(content: String) -> Result<Template> {
        Ok(Template { content })
    }

    fn to_template_context(scheme: &Scheme) -> HashMap<String, String> {
        let mut context = HashMap::new();

        context.insert("scheme-name".to_string(), scheme.name.clone());
        context.insert("scheme-author".to_string(), scheme.author.clone());
        context.insert(
            "scheme-description".to_string(),
            scheme.description.clone().unwrap_or_default(),
        );
        context.insert("scheme-slug".to_string(), scheme.slug.clone());
        context.insert(
            "scheme-slug-underscored".to_string(),
            scheme.slug.replace('-', "_"),
        );
        context.insert("scheme-system".to_string(), scheme.system.clone());
        context.insert("scheme-variant".to_string(), scheme.variant.clone());
        context.insert(
            format!("scheme-is-{}-variant", scheme.variant),
            "true".to_string(),
        );

        for (name, color) in scheme.palette.iter() {
            let hex = color.hex.clone();
            let rgb = color.rgb;

            context.insert(
                format!("{}-hex", name),
                format!("{}{}{}", color.hex.0, color.hex.1, color.hex.2),
            );
            context.insert(
                format!("{}-hex-bgr", name),
                format!("{}{}{}", color.hex.2, color.hex.1, color.hex.0),
            );
            context.insert(format!("{}-hex-r", name), hex.0);
            context.insert(format!("{}-hex-g", name), hex.1);
            context.insert(format!("{}-hex-b", name), hex.2);
            context.insert(format!("{}-rgb-r", name), rgb.0.to_string());
            context.insert(format!("{}-rgb-g", name), rgb.1.to_string());
            context.insert(format!("{}-rgb-b", name), rgb.2.to_string());
            context.insert(format!("{}-dec-r", name), (rgb.0 / 255).to_string());
            context.insert(format!("{}-dec-g", name), (rgb.1 / 255).to_string());
            context.insert(format!("{}-dec-b", name), (rgb.2 / 255).to_string());
        }

        context
    }

    pub fn render_to_file(&self, output_path: &Path, scheme: &Scheme) -> Result<&Self> {
        let tpl = RamhornsTemplate::new(self.content.clone()).unwrap();
        let context = Self::to_template_context(scheme);
        let rendered = tpl.render(&context);

        write_to_file(output_path, &rendered)?;

        Ok(self)
    }
}