check for empty cloze cards when rendering as well

This commit is contained in:
Damien Elmes 2020-05-14 21:56:45 +10:00
parent 782911471b
commit 24ffb6ab76
5 changed files with 39 additions and 9 deletions

View file

@ -169,9 +169,7 @@ class AddCards(QDialog):
showWarning(problem, help="AddItems#AddError") showWarning(problem, help="AddItems#AddError")
return None return None
if note.model()["type"] == MODEL_CLOZE: if note.model()["type"] == MODEL_CLOZE:
if not self.mw.col.models._availClozeOrds( if not note.cloze_numbers_in_fields():
note.model(), note.joinedFields(), False
):
if not askUser( if not askUser(
_( _(
"You have a cloze deletion note type " "You have a cloze deletion note type "

View file

@ -37,3 +37,6 @@ card-template-rendering-no-such-field =
# either due to a badly-designed template, or because required fields # either due to a badly-designed template, or because required fields
# are missing. # are missing.
card-template-rendering-empty-front = The front of this card is blank. card-template-rendering-empty-front = The front of this card is blank.
card-template-rendering-missing-cloze = No cloze { $number } found on card.
Please either add a cloze deletion, or use the Empty Cards tool.

View file

@ -312,6 +312,10 @@ impl NoteType {
}) })
.next() .next()
} }
pub(crate) fn is_cloze(&self) -> bool {
matches!(self.config.kind(), NoteTypeKind::Cloze)
}
} }
impl From<NoteType> for NoteTypeProto { impl From<NoteType> for NoteTypeProto {

View file

@ -109,7 +109,8 @@ impl Collection {
) )
}; };
let (qnodes, anodes) = render_card(qfmt, afmt, &field_map, card.ord, &self.i18n)?; let (qnodes, anodes) =
render_card(qfmt, afmt, &field_map, card.ord, nt.is_cloze(), &self.i18n)?;
Ok(RenderCardOutput { qnodes, anodes }) Ok(RenderCardOutput { qnodes, anodes })
} }

View file

@ -2,8 +2,8 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::err::{AnkiError, Result, TemplateError}; use crate::err::{AnkiError, Result, TemplateError};
use crate::i18n::{tr_strs, I18n, TR}; use crate::i18n::{tr_args, tr_strs, I18n, TR};
use crate::template_filters::apply_filters; use crate::{cloze::add_cloze_numbers_in_string, template_filters::apply_filters};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::{tag, take_until}; use nom::bytes::complete::{tag, take_until};
@ -23,6 +23,8 @@ static TEMPLATE_ERROR_LINK: &str =
"https://anki.tenderapp.com/kb/problems/card-template-has-a-problem"; "https://anki.tenderapp.com/kb/problems/card-template-has-a-problem";
static TEMPLATE_BLANK_LINK: &str = static TEMPLATE_BLANK_LINK: &str =
"https://anki.tenderapp.com/kb/card-appearance/the-front-of-this-card-is-blank"; "https://anki.tenderapp.com/kb/card-appearance/the-front-of-this-card-is-blank";
static TEMPLATE_BLANK_CLOZE_LINK: &str =
"https://anki.tenderapp.com/kb/problems/no-cloze-found-on-card";
// Lexing // Lexing
//---------------------------------------- //----------------------------------------
@ -521,6 +523,7 @@ pub fn render_card(
afmt: &str, afmt: &str,
field_map: &HashMap<&str, Cow<str>>, field_map: &HashMap<&str, Cow<str>>,
card_ord: u16, card_ord: u16,
is_cloze: bool,
i18n: &I18n, i18n: &I18n,
) -> Result<(Vec<RenderedNode>, Vec<RenderedNode>)> { ) -> Result<(Vec<RenderedNode>, Vec<RenderedNode>)> {
// prepare context // prepare context
@ -537,7 +540,20 @@ pub fn render_card(
.map_err(|e| template_error_to_anki_error(e, true, i18n))?; .map_err(|e| template_error_to_anki_error(e, true, i18n))?;
// check if the front side was empty // check if the front side was empty
if !qtmpl.renders_with_fields(context.nonempty_fields) { if is_cloze {
if cloze_is_empty(field_map, card_ord) {
let info = format!(
"<div>{}<br><a href='{}'>{}</a></div>",
i18n.trn(
TR::CardTemplateRenderingMissingCloze,
tr_args!["number"=>card_ord+1]
),
TEMPLATE_BLANK_CLOZE_LINK,
i18n.tr(TR::CardTemplateRenderingMoreInfo)
);
qnodes.push(RenderedNode::Text { text: info });
}
} else if !qtmpl.renders_with_fields(context.nonempty_fields) {
let info = format!( let info = format!(
"<div>{}<br><a href='{}'>{}</a></div>", "<div>{}<br><a href='{}'>{}</a></div>",
i18n.tr(TR::CardTemplateRenderingEmptyFront), i18n.tr(TR::CardTemplateRenderingEmptyFront),
@ -545,7 +561,7 @@ pub fn render_card(
i18n.tr(TR::CardTemplateRenderingMoreInfo) i18n.tr(TR::CardTemplateRenderingMoreInfo)
); );
qnodes.push(RenderedNode::Text { text: info }); qnodes.push(RenderedNode::Text { text: info });
}; }
// answer side // answer side
context.question_side = false; context.question_side = false;
@ -556,6 +572,14 @@ pub fn render_card(
Ok((qnodes, anodes)) Ok((qnodes, anodes))
} }
fn cloze_is_empty(field_map: &HashMap<&str, Cow<str>>, card_ord: u16) -> bool {
let mut set = HashSet::with_capacity(4);
for field in field_map.values() {
add_cloze_numbers_in_string(field.as_ref(), &mut set);
}
!set.contains(&(card_ord + 1))
}
// Field requirements // Field requirements
//---------------------------------------- //----------------------------------------
@ -1063,7 +1087,7 @@ mod test {
let i18n = I18n::new(&[""], "", log::terminal()); let i18n = I18n::new(&[""], "", log::terminal());
use crate::template::RenderedNode as FN; use crate::template::RenderedNode as FN;
let qnodes = super::render_card("test{{E}}", "", &map, 1, &i18n) let qnodes = super::render_card("test{{E}}", "", &map, 1, false, &i18n)
.unwrap() .unwrap()
.0; .0;
assert_eq!( assert_eq!(