From 930c97b1c7d975cb106bac875f4e04466443b07e Mon Sep 17 00:00:00 2001 From: James Elmore Date: Mon, 24 Jun 2024 03:39:56 -0400 Subject: [PATCH] Fix Renaming note fields not updating custom browser appearance (#3245) * Added methods to parse browser templates * Added method to get parsed browser templates * Make field rename check browser templates for field updates * Update tests * Updated CONTRIBUTORS * Formatting * Refactored cloze field logic for question template into closure * Refactored cloze field logic for answer template into closure --- CONTRIBUTORS | 1 + rslib/src/notetype/mod.rs | 68 +++++++++++++++++++++++++++++---- rslib/src/notetype/templates.rs | 7 ++++ 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index ffc7bb7af..d1db7eebc 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -176,6 +176,7 @@ Wu Yi-Wei RRomeroJr <117.rromero@gmail.com> Xidorn Quan Alexander Bocken +James Elmore ******************** diff --git a/rslib/src/notetype/mod.rs b/rslib/src/notetype/mod.rs index 7afae3741..52489e618 100644 --- a/rslib/src/notetype/mod.rs +++ b/rslib/src/notetype/mod.rs @@ -495,13 +495,18 @@ impl Notetype { self.reposition_sort_idx(); let mut parsed_templates = self.parsed_templates(); + let mut parsed_browser_templates = self.parsed_browser_templates(); let reqs = self.updated_requirements(&parsed_templates); // handle renamed+deleted fields if let Some(existing) = existing { let fields = self.renamed_and_removed_fields(existing); if !fields.is_empty() { - self.update_templates_for_renamed_and_removed_fields(fields, &mut parsed_templates); + self.update_templates_for_renamed_and_removed_fields( + fields, + &mut parsed_templates, + &mut parsed_browser_templates, + ); } } self.config.reqs = reqs; @@ -556,24 +561,49 @@ impl Notetype { &mut self, fields: HashMap>, parsed: &mut [(Option, Option)], + parsed_browser: &mut [(Option, Option)], ) { let first_remaining_field_name = &self.fields.first().unwrap().name; let is_cloze = self.is_cloze(); - for (idx, (q_opt, a_opt)) in parsed.iter_mut().enumerate() { + + let q_update_fields = |q_opt: &mut Option, template_target: &mut String| { if let Some(q) = q_opt { q.rename_and_remove_fields(&fields); if !q.contains_field_replacement() || is_cloze && !q.contains_cloze_replacement() { q.add_missing_field_replacement(first_remaining_field_name, is_cloze); } - self.templates[idx].config.q_format = q.template_to_string(); + *template_target = q.template_to_string(); } + }; + + let a_update_fields = |a_opt: &mut Option, template_target: &mut String| { if let Some(a) = a_opt { a.rename_and_remove_fields(&fields); if is_cloze && !a.contains_cloze_replacement() { a.add_missing_field_replacement(first_remaining_field_name, is_cloze); } - self.templates[idx].config.a_format = a.template_to_string(); + *template_target = a.template_to_string(); } + }; + + // Update main templates + for (idx, (q_opt, a_opt)) in parsed.iter_mut().enumerate() { + q_update_fields(q_opt, &mut self.templates[idx].config.q_format); + + a_update_fields(a_opt, &mut self.templates[idx].config.a_format); + } + + // Update browser templates, if they exist + for (idx, (q_browser_opt, a_browser_opt)) in parsed_browser.iter_mut().enumerate() { + q_update_fields( + q_browser_opt, + &mut self.templates[idx].config.q_format_browser, + ); + + a_update_fields( + a_browser_opt, + &mut self.templates[idx].config.a_format_browser, + ); } } @@ -583,6 +613,17 @@ impl Notetype { .map(|t| (t.parsed_question(), t.parsed_answer())) .collect() } + fn parsed_browser_templates(&self) -> Vec<(Option, Option)> { + self.templates + .iter() + .map(|t| { + ( + t.parsed_question_format_for_browser(), + t.parsed_answer_format_for_browser(), + ) + }) + .collect() + } fn fix_field_names(&mut self) -> Result<()> { self.fields.iter_mut().try_for_each(NoteField::fix_name) @@ -790,12 +831,17 @@ mod test { nt_norm.add_template("Card 1", "front {{foo}}", "back {{bar}}"); nt_norm.templates[0].ord = Some(0); let mut parsed = nt_norm.parsed_templates(); + let mut parsed_browser = nt_norm.parsed_browser_templates(); let mut field_map: HashMap> = HashMap::new(); field_map.insert("foo".to_owned(), None); field_map.insert("bar".to_owned(), None); - nt_norm.update_templates_for_renamed_and_removed_fields(field_map, &mut parsed); + nt_norm.update_templates_for_renamed_and_removed_fields( + field_map, + &mut parsed, + &mut parsed_browser, + ); assert_eq!(nt_norm.templates[0].config.q_format, "front {{baz}}"); assert_eq!(nt_norm.templates[0].config.a_format, "back "); @@ -815,7 +861,11 @@ mod test { field_map.insert("foo".to_owned(), None); field_map.insert("bar".to_owned(), None); - nt_cloze.update_templates_for_renamed_and_removed_fields(field_map, &mut parsed); + nt_cloze.update_templates_for_renamed_and_removed_fields( + field_map, + &mut parsed, + &mut parsed_browser, + ); assert_eq!(nt_cloze.templates[0].config.q_format, "front {{cloze:baz}}"); assert_eq!(nt_cloze.templates[0].config.a_format, "back {{cloze:baz}}"); @@ -837,7 +887,11 @@ mod test { let mut field_map: HashMap> = HashMap::new(); field_map.insert("bar".to_owned(), None); - nt_cloze.update_templates_for_renamed_and_removed_fields(field_map, &mut parsed); + nt_cloze.update_templates_for_renamed_and_removed_fields( + field_map, + &mut parsed, + &mut parsed_browser, + ); assert_eq!(nt_cloze.templates[0].config.q_format, "front {{cloze:foo}}"); assert_eq!(nt_cloze.templates[0].config.a_format, "back {{cloze:foo}}"); } diff --git a/rslib/src/notetype/templates.rs b/rslib/src/notetype/templates.rs index aba9afb7a..26f6c3de2 100644 --- a/rslib/src/notetype/templates.rs +++ b/rslib/src/notetype/templates.rs @@ -24,6 +24,13 @@ impl CardTemplate { ParsedTemplate::from_text(&self.config.a_format).ok() } + pub(crate) fn parsed_question_format_for_browser(&self) -> Option { + ParsedTemplate::from_text(&self.config.q_format_browser).ok() + } + + pub(crate) fn parsed_answer_format_for_browser(&self) -> Option { + ParsedTemplate::from_text(&self.config.a_format_browser).ok() + } pub(crate) fn question_format_for_browser(&self) -> &str { if !self.config.q_format_browser.is_empty() { &self.config.q_format_browser