cook_markdown/
lib.rs

1use std::ops::Not;
2use cook_with_rust_parser::*;
3
4
5pub fn recipe_to_markdown(recipe: &Recipe) -> String {
6    let mut ingredient_specifier_iter = recipe.metadata.ingredients_specifiers.iter();
7    let mut cookware_iter = recipe.metadata.cookware.iter();
8    let mut timer_iter = recipe.metadata.timer.iter();
9    let mut result_string = String::new();
10
11    if recipe.metadata.ingredients.is_empty().not() {
12        result_string += "### Ingredients\n";
13        result_string += "| Ingredient | Amount | Unit |\n";
14        result_string += "|------------|--------|------|\n";
15
16        let ingredients = recipe.metadata.ingredients.values();
17        ingredients.for_each(|e| {
18            let amount = match &e.amount {
19                Some(d) => {
20                    match d {
21                        Amount::Multi(dd) => {
22                            format!("servings * {}", dd)
23                        }
24                        Amount::Servings(dd) => {
25                            let mut servings = String::new();
26                            dd.iter().for_each(|a| {
27                                servings.push_str(&a.to_string());
28                                servings.push('|');
29                            });
30                            servings.pop();
31                            servings
32                        }
33                        Amount::Single(dd) => {
34                            dd.to_string()
35                        }
36                    }
37                },
38                None => "-".to_string(),
39            };
40            let unit = match &e.unit {
41                None => "-".to_string(),
42                Some(u) => u.to_string(),
43            };
44            let line = format!("| {} | {} | {} |\n", e.name, amount, unit);
45            result_string += &line;
46        });
47        result_string += "\n"
48    }
49
50    if recipe.metadata.cookware.is_empty().not() {
51        result_string += "\n### Cookware:\n";
52        recipe.metadata.cookware.iter().for_each(|cookw| {
53            result_string += format!("* {}\n", cookw).as_str();
54        });
55    }
56
57    recipe.instruction.chars().for_each(|char| {
58        if char == '@' {
59            let insert_ingredient = ingredient_specifier_iter.next().unwrap();
60            let ingredient_referenced = recipe.metadata.ingredients.get(&insert_ingredient.ingredient).unwrap();
61            let ingredient_name = &ingredient_referenced.name;
62            let ingredient_unit = match &ingredient_referenced.unit {
63                None => "".to_string(),
64                Some(d) => {
65                    let mut res = String::from(' ');
66                    res.push_str(d.as_str());
67                    res
68                },
69            };
70            let ingredient_amount = match &insert_ingredient.amount_in_step {
71                Amount::Multi(d) => {
72                    format!(" *{}", d)
73                }
74                Amount::Servings(dd) => {
75                    let mut servings = String::new();
76                    servings.push(' ');
77                    dd.iter().for_each(|a| {
78                        servings.push_str(&a.to_string());
79                        servings.push('|');
80                    });
81                    servings.pop();
82                    // servings.push(' ');
83                    servings
84                }
85                Amount::Single(d) => {
86                    let mut res = String::from(' ');
87                    res.push_str(d.to_string().as_str());
88                    // res.push(' ');
89                    res
90                }
91            };
92            let insert_string = format!("__{}{}{}__", ingredient_name, ingredient_amount, ingredient_unit);
93            result_string += &insert_string;
94        } else if char == '#' {
95            result_string.push_str("_");
96            result_string.push_str(cookware_iter.next().unwrap());
97            result_string.push_str("_");
98        } else if char == '~' {
99            let timer = timer_iter.next().unwrap();
100            result_string.push_str("__");
101            result_string.push_str(&timer.amount.to_string());
102            result_string.push(' ');
103            result_string.push_str(&timer.unit);
104            result_string.push_str("__");
105        } else {
106            result_string.push(char);
107        }
108    });
109
110    result_string
111}
112
113#[cfg(test)]
114mod tests {
115    use std::fs::read_to_string;
116    use cook_with_rust_parser::parse;
117    use crate::recipe_to_markdown;
118
119    #[test]
120    fn it_works() {
121        let inp = read_to_string("../spec/examples/Coffee Souffle.cook").unwrap();
122        let recipe = parse(&inp).unwrap();
123
124        let _result = recipe_to_markdown(&recipe);
125
126        // std::fs::write("TEST.md", result);
127    }
128}