diff --git a/pylib/anki/cards.py b/pylib/anki/cards.py index b7f845e83..75ff244f5 100644 --- a/pylib/anki/cards.py +++ b/pylib/anki/cards.py @@ -178,10 +178,8 @@ class Card: total = int((time.time() - self.timerStarted) * 1000) return min(total, self.timeLimit()) - def isEmpty(self) -> Optional[bool]: - ords = self.col.models.availOrds(self.model(), joinFields(self.note().fields)) - if self.ord not in ords: - return True + # legacy + def isEmpty(self) -> bool: return False def __repr__(self) -> str: diff --git a/pylib/anki/models.py b/pylib/anki/models.py index 4f31e56f3..5f3a31a7f 100644 --- a/pylib/anki/models.py +++ b/pylib/anki/models.py @@ -520,7 +520,7 @@ class ModelManager: # Required field/text cache ########################################################################## - # fixme: clayout, importing, cards.isEmpty + # fixme: clayout, importing def availOrds(self, m: NoteType, flds: str) -> List: "Given a joined field string, return available template ordinals." if m["type"] == MODEL_CLOZE: diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index 743cc3087..b03291409 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -180,14 +180,7 @@ class Reviewer: self.typedAnswer: str = None c = self.card # grab the question and play audio - if c.isEmpty(): - q = _( - """\ -The front of this card is empty. Please run Tools>Empty Cards.""" - ) - else: - q = c.q() - + q = c.q() # play audio? if c.autoplay(): av_player.play_tags(c.question_av_tags()) diff --git a/rslib/src/template.rs b/rslib/src/template.rs index 7ec6d0a01..c38be0bfa 100644 --- a/rslib/src/template.rs +++ b/rslib/src/template.rs @@ -532,19 +532,19 @@ pub fn render_card( }; // question side - let (qnodes, qtmpl) = ParsedTemplate::from_text(qfmt) + let (mut qnodes, qtmpl) = ParsedTemplate::from_text(qfmt) .and_then(|tmpl| Ok((tmpl.render(&context)?, tmpl))) .map_err(|e| template_error_to_anki_error(e, true, i18n))?; // check if the front side was empty if !qtmpl.renders_with_fields(context.nonempty_fields) { let info = format!( - "{}
{}", + "
{}
{}
", i18n.tr(TR::CardTemplateRenderingEmptyFront), TEMPLATE_BLANK_LINK, i18n.tr(TR::CardTemplateRenderingMoreInfo) ); - return Err(AnkiError::TemplateError { info }); + qnodes.push(RenderedNode::Text { text: info }); }; // answer side @@ -728,7 +728,11 @@ fn nodes_to_string(buf: &mut String, nodes: &[ParsedNode]) { mod test { use super::{FieldMap, ParsedNode::*, ParsedTemplate as PT}; use crate::err::TemplateError; - use crate::template::{field_is_empty, nonempty_fields, FieldRequirements, RenderContext}; + use crate::{ + i18n::I18n, + log, + template::{field_is_empty, nonempty_fields, FieldRequirements, RenderContext}, + }; use std::collections::{HashMap, HashSet}; use std::iter::FromIterator; @@ -1012,4 +1016,30 @@ mod test { }] ); } + + #[test] + fn render_card() { + let map: HashMap<_, _> = vec![("E", "")] + .into_iter() + .map(|r| (r.0, r.1.into())) + .collect(); + + let i18n = I18n::new(&[""], "", log::terminal()); + use crate::template::RenderedNode as FN; + + let qnodes = super::render_card("test{{E}}", "", &map, 1, &i18n) + .unwrap() + .0; + assert_eq!( + qnodes[0], + FN::Text { + text: "test".into() + } + ); + if let FN::Text { ref text } = qnodes[1] { + assert!(text.contains("card is blank")); + } else { + assert!(false); + } + } }