emoji_crafter/renderer/
template_renderer.rs

1use crate::document::Emoji;
2use crate::manifest::*;
3use rayon::prelude::*;
4use serde::Serialize;
5use std::path::PathBuf;
6use tinytemplate::TinyTemplate;
7
8#[derive(Serialize)]
9pub struct Renderable {
10    path: PathBuf,
11    newline: String,
12    emojiset: Emojiset,
13    emojis: Vec<RenderableEmoji>,
14    themes: Vec<Theme>,
15    outputs: Vec<Output>,
16}
17
18#[derive(Serialize)]
19pub struct RenderableEmoji {
20    id: String,
21    name: String,
22    is_animation: bool,
23    is_image: bool,
24}
25
26pub trait OnProgress<'a>: Fn(&'a Template) {}
27
28impl<'a, T> OnProgress<'a> for T where T: Fn(&'a Template) {}
29
30pub fn process(project: &Project, emojis: &Vec<Emoji>) -> Renderable {
31    let mut renderable_emoji: Vec<RenderableEmoji> = emojis
32        .par_iter()
33        .filter_map(|emoji| match emoji {
34            Emoji::Animation { id, name, .. } => Some(RenderableEmoji {
35                id: id.clone(),
36                name: name.clone(),
37                is_animation: true,
38                is_image: false,
39            }),
40            Emoji::Image { id, name, .. } => Some(RenderableEmoji {
41                id: id.clone(),
42                name: name.clone(),
43                is_animation: false,
44                is_image: true,
45            }),
46            _ => None,
47        })
48        .collect();
49
50    renderable_emoji.par_sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap());
51
52    Renderable {
53        path: project.path.clone(),
54        newline: "\n".into(),
55        emojiset: project.emojiset.clone(),
56        emojis: renderable_emoji,
57        themes: project.themes.clone(),
58        outputs: project.outputs.clone(),
59    }
60}
61
62pub fn render<'a, F>(context: &Renderable, templates: &'a Vec<Template>, on_progress: F)
63where
64    F: OnProgress<'a> + Sync + Send,
65{
66    templates.par_iter().for_each(|template| {
67        let mut renderer = TinyTemplate::new();
68
69        let input_path = context.path.join(template.input.clone());
70        let output_path = context.path.join(template.output.clone());
71
72        let input = std::fs::read_to_string(&input_path).unwrap();
73
74        renderer.add_template("current", &input).unwrap();
75
76        match renderer.render("current", &context) {
77            Ok(output) => {
78                std::fs::write(&output_path, output).unwrap();
79            }
80            Err(error) => {
81                println!("{}", error);
82
83                std::process::exit(1);
84            }
85        }
86
87        on_progress(template);
88    });
89}