Skip to content

Commit

Permalink
Merge pull request #21 from cooklang/yaml_frontmatter
Browse files Browse the repository at this point in the history
Yaml frontmatter
  • Loading branch information
dubadub authored Dec 4, 2024
2 parents 5aef19f + 97dd329 commit 34e3a82
Show file tree
Hide file tree
Showing 19 changed files with 745 additions and 415 deletions.
2 changes: 0 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ thiserror = "1"
url = { version = "2", features = ["serde"] }
pest = { version = "2", optional = true }
pest_derive = { version = "2", optional = true }
indexmap = { version = "2", features = ["serde"] }
emojis = "0.6"
toml = { version = "0.8", optional = true }
once_cell = "1"
Expand All @@ -32,10 +31,10 @@ finl_unicode = { version = "1.2", features = ["categories"], default-features =
smallvec = { version = "1" }
unicase = "2.7.0"
yansi = "1.0.1"
serde_yaml = "0.9.34"

[dev-dependencies]
serde_json = "1"
serde_yaml = "0.9"
criterion = "0.5"
test-case = "3.2.1"
indoc = "2.0.3"
Expand Down
57 changes: 57 additions & 0 deletions benches/frontmatter_test_recipe.cook
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
servings: 4
emoji: 🥟
tags: warm, fried, starter
source: CooklangCLI Seed <https://github.com/cooklang/CookCLI/blob/main/seed/Potstickers.cook>
prep time: 20 min
cook time: 30 min
---

[- Same recipe, same metadata. Just in a YAML frontmatter now -]


Let's first make some dough. Set kettle with some water and prepare
@strong white flour{75%g} and @plain flour{75%g}.

Put the flours into a bowl. Mix the @just-boiled water{75%ml} with the
@salt{2%tsp}, then add this to the flour, mixing it in with a knife. It will
seem very floury to start with but keep going and it will come together. Don’t
be tempted to add more water. Cover with a damp cloth for 10 minutes, then
remove and knead until the dough is smooth and elastic. Cover the dough again
and leave it to stand somewhere warm for an hour.

Cut the dough into 2 equal pieces and dust your work surface with flour. Roll
the dough out as thinly as you can. It will be resistant to start with, but you
will eventually end up with a round about 35cm in diameter and with a thickness
of less than 1mm.

Cut the dough into rounds using a 9cm cutter, then repeat with the other piece
of dough. Knead the offcuts together and roll again. You should end up with at
least 24 discs. Dust with flour in between each one if you want to stack them
together.

Heat the @olive oil{1%tbsp} in a frying pan and gently cook very finely shredded
and chopped @Chinese cabbage{100%g}, very finely grated @carrot{50%g} and finely
chopped @spring onions{3%items} until they have wilted down. Remove from the
heat and stir in very finely chopped @strained kimchi{75%g}. Taste for seasoning
and add salt and pepper if you think it necessary. Allow to cool.

Assemble the dumplings by putting a teaspoon of filling in the centre of each
wrapper. Wet around the sides – thoroughly, as they can sometimes crack – then
pinch the edges together, pleating from the middle down each side to seal.

Make the dipping sauce by mixing @soy sauce{2%tbsp}, @rice wine vinegar{1%tbsp},
@chilli oil{1%tbsp} and @sesame oil{1%tsp} together. Taste for seasoning and add
salt if necessary.

To cook, heat @olive oil{3%tbsp} in a non-stick frying pan that has a lid – you
need just enough oil to thinly cover the base. Add some of the dumplings, making
sure they are well spread out.

Fry the dumplings over a medium heat until they are crisp and brown underneath,
then add water – just enough to thinly cover the base of the pan. Cover the pan
quickly, as it will spit when you add the water, and steam the dumplings for 5
minutes, until they are starting to look translucent and the water has
evaporated. Uncover and cook for a further minute to make sure the underside is
still crisp. Remove and keep warm while you cook the rest. Serve hot with the
dipping sauce.
6 changes: 6 additions & 0 deletions benches/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use criterion::{criterion_group, criterion_main, Criterion};
use cooklang::{parser::PullParser, CooklangParser, Extensions};

const TEST_RECIPE: &str = include_str!("./test_recipe.cook");
const FRONTMATTER_RECIPE: &str = include_str!("./frontmatter_test_recipe.cook");
const COMPLEX_TEST_RECIPE: &str = include_str!("./complex_test_recipe.cook");

fn canonical(c: &mut Criterion) {
Expand All @@ -26,6 +27,11 @@ fn canonical(c: &mut Criterion) {
group.bench_with_input("meta", TEST_RECIPE, |b, input| {
b.iter(|| extended.parse_metadata(input).is_valid())
});
group.bench_with_input("frontmatter_meta", FRONTMATTER_RECIPE, |b, input| {
{
b.iter(|| extended.parse_metadata(input).is_valid())
}
});
}

fn extended(c: &mut Criterion) {
Expand Down
11 changes: 8 additions & 3 deletions bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,14 @@ pub fn parse_metadata(input: String) -> CooklangMetadata {
.unwrap_output();

// converting IndexMap into HashMap
let _ = &(parsed).iter().for_each(|(key, value)| {
metadata.insert(key.to_string(), value.to_string());
});
let _ = &(parsed)
.iter()
.for_each(|(key, value)| match (key.as_str(), value.as_str()) {
(Some(key), Some(value)) => {
metadata.insert(key.to_string(), value.to_string());
}
_ => {}
});

metadata
}
Expand Down
52 changes: 36 additions & 16 deletions bindings/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,32 +221,45 @@ pub(crate) fn merge_grouped_quantities(left: &mut GroupedQuantity, right: &Group
// TODO define rules on language spec level

right.iter().for_each(|(key, value)| {
left
.entry(key.clone()) // isn't really necessary?
left.entry(key.clone()) // isn't really necessary?
.and_modify(|v| {
match key.unit_type {
QuantityType::Number => {
let Value::Number { value: assignable } = value else { panic!("Unexpected type") };
let Value::Number { value: stored } = v else { panic!("Unexpected type") };
let Value::Number { value: assignable } = value else {
panic!("Unexpected type")
};
let Value::Number { value: stored } = v else {
panic!("Unexpected type")
};

*stored += assignable
},
}
QuantityType::Range => {
let Value::Range { start, end } = value else { panic!("Unexpected type") };
let Value::Range { start: s, end: e } = v else { panic!("Unexpected type") };
let Value::Range { start, end } = value else {
panic!("Unexpected type")
};
let Value::Range { start: s, end: e } = v else {
panic!("Unexpected type")
};

// is it even correct?
*s += start;
*e += end;
},
}
QuantityType::Text => {
let Value::Text { value: ref assignable } = value else { panic!("Unexpected type") };
let Value::Text { value: stored } = v else { panic!("Unexpected type") };
let Value::Text {
value: ref assignable,
} = value
else {
panic!("Unexpected type")
};
let Value::Text { value: stored } = v else {
panic!("Unexpected type")
};

*stored += assignable;
},
QuantityType::Empty => {}, // nothing is required to do, Some + Some = Some

}
QuantityType::Empty => {} // nothing is required to do, Some + Some = Some
}
})
.or_insert(value.clone());
Expand Down Expand Up @@ -332,9 +345,16 @@ pub(crate) fn into_simple_recipe(recipe: &OriginalRecipe) -> CooklangRecipe {
});
});

recipe.metadata.map.iter().for_each(|(key, value)| {
metadata.insert(key.to_string(), value.to_string());
});
recipe
.metadata
.map
.iter()
.for_each(|(key, value)| match (key.as_str(), value.as_str()) {
(Some(key), Some(value)) => {
metadata.insert(key.to_string(), value.to_string());
}
_ => {}
});

CooklangRecipe {
metadata,
Expand Down
2 changes: 1 addition & 1 deletion playground/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ fn render(r: cooklang::ScaledRecipe, converter: &Converter) -> String {
ul {
@for (key, value) in &r.metadata.map {
li.metadata {
span.key { (key) } ":" (value)
span.key { (key.as_str().unwrap_or("<not string key>")) } ":" (value.as_str().unwrap_or("<not string value>")) // TODO
}
}
}
Expand Down
Loading

0 comments on commit 34e3a82

Please sign in to comment.