@@ -102,6 +102,7 @@ pub fn deref_timer(recipe: &Arc<CooklangRecipe>, index: u32) -> Timer {
102102pub fn parse_aisle_config ( input : String ) -> Arc < AisleConf > {
103103 let mut categories: Vec < AisleCategory > = Vec :: new ( ) ;
104104 let mut cache: AisleReverseCategory = AisleReverseCategory :: default ( ) ;
105+ let mut common_names: std:: collections:: HashMap < String , String > = std:: collections:: HashMap :: new ( ) ;
105106
106107 // Use the lenient parser that handles duplicates as warnings
107108 let result = parse_lenient ( & input) ;
@@ -131,16 +132,18 @@ pub fn parse_aisle_config(input: String) -> Arc<AisleConf> {
131132 // building cache
132133 category. ingredients . iter ( ) . for_each ( |i| {
133134 cache. insert ( i. name . clone ( ) , category. name . clone ( ) ) ;
135+ common_names. insert ( i. name . to_lowercase ( ) , i. name . clone ( ) ) ;
134136
135137 i. aliases . iter ( ) . for_each ( |a| {
136138 cache. insert ( a. to_string ( ) , category. name . clone ( ) ) ;
139+ common_names. insert ( a. to_lowercase ( ) , i. name . clone ( ) ) ;
137140 } ) ;
138141 } ) ;
139142
140143 categories. push ( category) ;
141144 } ) ;
142145
143- let config = AisleConf { categories, cache } ;
146+ let config = AisleConf { categories, cache, common_names } ;
144147
145148 Arc :: new ( config)
146149}
@@ -178,6 +181,24 @@ pub fn combine_ingredients_selected(
178181 combined
179182}
180183
184+ /// Replaces ingredient names with their common names from aisle configuration
185+ ///
186+ /// # Arguments
187+ /// * `list` - The ingredient list to normalize
188+ /// * `aisle` - The aisle configuration containing common name mappings
189+ ///
190+ /// # Returns
191+ /// A new ingredient list with names replaced by their common names
192+ #[ uniffi:: export]
193+ pub fn use_common_names ( list : IngredientList , aisle : & AisleConf ) -> IngredientList {
194+ let mut normalized: IngredientList = IngredientList :: default ( ) ;
195+ for ( ingredient_name, quantity) in list. iter ( ) {
196+ let common_name = aisle. common_name_for ( ingredient_name. clone ( ) ) ;
197+ add_to_ingredient_list ( & mut normalized, & common_name, & quantity) ;
198+ }
199+ normalized
200+ }
201+
181202// Metadata helper functions
182203/// Gets the servings from recipe metadata
183204///
@@ -886,6 +907,74 @@ dried oregano
886907 ) ;
887908 }
888909
910+ #[ test]
911+ fn test_use_common_names ( ) {
912+ use crate :: {
913+ combine_ingredients, parse_aisle_config, use_common_names, Amount , Ingredient , Value ,
914+ } ;
915+
916+ let ingredients = vec ! [
917+ Ingredient {
918+ name: "apples" . to_string( ) ,
919+ amount: Some ( Amount {
920+ quantity: Value :: Number { value: 3.0 } ,
921+ units: None ,
922+ } ) ,
923+ descriptor: None ,
924+ reference: None ,
925+ } ,
926+ Ingredient {
927+ name: "eggs" . to_string( ) ,
928+ amount: Some ( Amount {
929+ quantity: Value :: Number { value: 2.0 } ,
930+ units: None ,
931+ } ) ,
932+ descriptor: None ,
933+ reference: None ,
934+ } ,
935+ Ingredient {
936+ name: "salt" . to_string( ) ,
937+ amount: Some ( Amount {
938+ quantity: Value :: Number { value: 1.0 } ,
939+ units: Some ( "tsp" . to_string( ) ) ,
940+ } ) ,
941+ descriptor: None ,
942+ reference: None ,
943+ } ,
944+ ] ;
945+
946+ let aisle = parse_aisle_config (
947+ r#"
948+ [fruit and veg]
949+ apple gala | apples
950+ aubergine
951+
952+ [milk and dairy]
953+ egg | eggs
954+ "#
955+ . to_string ( ) ,
956+ ) ;
957+
958+ let combined = combine_ingredients ( & ingredients) ;
959+
960+ // "apples" should exist before common names
961+ assert ! ( combined. contains_key( "apples" ) ) ;
962+ assert ! ( combined. contains_key( "eggs" ) ) ;
963+
964+ let normalized = use_common_names ( combined, & aisle) ;
965+
966+ // "apples" should be replaced by common name "apple gala"
967+ assert ! ( normalized. contains_key( "apple gala" ) ) ;
968+ assert ! ( !normalized. contains_key( "apples" ) ) ;
969+
970+ // "eggs" should be replaced by common name "egg"
971+ assert ! ( normalized. contains_key( "egg" ) ) ;
972+ assert ! ( !normalized. contains_key( "eggs" ) ) ;
973+
974+ // "salt" not in aisle config, should stay as is
975+ assert ! ( normalized. contains_key( "salt" ) ) ;
976+ }
977+
889978 #[ test]
890979 fn test_parse_recipe_with_note ( ) {
891980 use crate :: { parse_recipe, Block , Item } ;
0 commit comments