def render(self) -> TemplateRenderOutput: try: partial = self._partially_render() except TemplateError as e: return TemplateRenderOutput( question_text=str(e), answer_text=str(e), question_av_tags=[], answer_av_tags=[], ) qtext = apply_custom_filters(partial.qnodes, self, front_side=None) qout = self.col()._backend.extract_av_tags(text=qtext, question_side=True) atext = apply_custom_filters(partial.anodes, self, front_side=qout.text) aout = self.col()._backend.extract_av_tags(text=atext, question_side=False) output = TemplateRenderOutput( question_text=qout.text, answer_text=aout.text, question_av_tags=av_tags_to_native(qout.av_tags), answer_av_tags=av_tags_to_native(aout.av_tags), css=self.note_type()["css"], ) if not self._browser: hooks.card_did_render(output, self) return output
def render(self) -> TemplateRenderOutput: try: partial = self._partially_render() except anki.rsbackend.TemplateError as e: return TemplateRenderOutput( question_text=str(e), answer_text=str(e), question_av_tags=[], answer_av_tags=[], ) qtext = apply_custom_filters(partial.qnodes, self, front_side=None) qtext, q_avtags = self.col().backend.extract_av_tags(qtext, True) atext = apply_custom_filters(partial.anodes, self, front_side=qtext) atext, a_avtags = self.col().backend.extract_av_tags(atext, False) output = TemplateRenderOutput( question_text=qtext, answer_text=atext, question_av_tags=q_avtags, answer_av_tags=a_avtags, css=self.note_type()["css"], ) if not self._browser: hooks.card_did_render(output, self) return output
def render_card(col: anki.storage._Collection, card: Card, note: Note, browser: bool) -> TemplateRenderOutput: "Render a card." # collect data fields = fields_for_rendering(col, card, note) qfmt, afmt = templates_for_card(card, browser) ctx = TemplateRenderContext(col=col, card=card, note=note, fields=fields, qfmt=qfmt, afmt=afmt) # render try: output = render_card_from_context(ctx) except anki.rsbackend.TemplateError as e: output = TemplateRenderOutput( question_text=str(e), answer_text=str(e), question_av_tags=[], answer_av_tags=[], ) hooks.card_did_render(output, ctx) return output
def render_card(col: anki.storage._Collection, card: Card, note: Note, browser: bool) -> TemplateRenderOutput: "Render a card." # collect data fields = fields_for_rendering(col, card, note) qfmt, afmt = templates_for_card(card, browser) ctx = TemplateRenderContext(col=col, card=card, note=note, fields=fields, qfmt=qfmt, afmt=afmt) # render try: output = render_card_from_context(ctx) except anki.rsbackend.BackendException as e: errmsg = _("Card template has a problem:") + f"<br>{e}" output = TemplateRenderOutput( question_text=errmsg, answer_text=errmsg, question_av_tags=[], answer_av_tags=[], ) if not output.question_text.strip(): msg = _("The front of this card is blank.") help = _("More info") helplink = CARD_BLANK_HELP msg += f"<br><a href='{helplink}'>{help}</a>" output.question_text = msg hooks.card_did_render(output, ctx) return output
def _renderQA(self, data: QAData, qfmt: Optional[str] = None, afmt: Optional[str] = None) -> Dict[str, Union[str, int]]: "Returns hash of id, question, answer." # extract info from data split_fields = splitFields(data[6]) card_ord = data[4] model = self.models.get(data[2]) if model["type"] == MODEL_STD: template = model["tmpls"][data[4]] else: template = model["tmpls"][0] flag = data[7] deck_id = data[3] card_id = data[0] tags = data[5] qfmt = qfmt or template["qfmt"] afmt = afmt or template["afmt"] # create map of field names -> field content fields: Dict[str, str] = {} for (name, (idx, conf)) in list(self.models.fieldMap(model).items()): fields[name] = split_fields[idx] # add special fields fields["Tags"] = tags.strip() fields["Type"] = model["name"] fields["Deck"] = self.decks.name(deck_id) fields["Subdeck"] = fields["Deck"].split("::")[-1] fields["Card"] = template["name"] fields["CardFlag"] = self._flagNameFromCardFlags(flag) fields["c%d" % (card_ord + 1)] = "1" # legacy fields = runFilter("mungeFields", fields, model, data, self) # allow add-ons to modify the available fields & templates (qfmt, afmt) = hooks.card_will_render((qfmt, afmt), fields, model, data) # render fields qatext = render_card(self, qfmt, afmt, fields, card_ord) ret: Dict[str, Any] = dict(q=qatext[0], a=qatext[1], id=card_id) # allow add-ons to modify the generated result for type in "q", "a": ret[type] = hooks.card_did_render(ret[type], type, fields, model, data, self) # empty cloze? if type == "q" and model["type"] == MODEL_CLOZE: if not self.models._availClozeOrds(model, data[6], False): ret["q"] += "<p>" + _( "Please edit this note and add some cloze deletions. (%s)" ) % ("<a href=%s#cloze>%s</a>" % (HELP_SITE, _("help"))) return ret
def render_card(col: anki.storage._Collection, card: Card, note: Note, browser: bool) -> TemplateRenderOutput: "Render a card." # collect data fields = fields_for_rendering(col, card, note) qfmt, afmt = templates_for_card(card, browser) ctx = TemplateRenderContext(col=col, card=card, note=note, fields=fields, qfmt=qfmt, afmt=afmt) # render try: output = render_card_from_context(ctx) except anki.rsbackend.BackendException as e: # fixme: specific exception in 2.1.21 err = e.args[0].template_parse # pylint: disable=no-member if err.q_side: side = _("Front") else: side = _("Back") errmsg = _("{} template has a problem:").format(side) + f"<br>{e}" errmsg += "<br><a href=https://anki.tenderapp.com/kb/problems/card-template-has-a-problem>{}</a>".format( _("More info")) output = TemplateRenderOutput( question_text=errmsg, answer_text=errmsg, question_av_tags=[], answer_av_tags=[], ) if not output.question_text.strip(): msg = _("The front of this card is blank.") help = _("More info") helplink = CARD_BLANK_HELP msg += f"<br><a href='{helplink}'>{help}</a>" output.question_text = msg hooks.card_did_render(output, ctx) return output
def _renderQA(self, data: QAData, qfmt: Optional[str] = None, afmt: Optional[str] = None) -> Dict[str, Union[str, int]]: # extract info from data split_fields = splitFields(data[6]) card_ord = data[4] model = self.models.get(data[2]) if model["type"] == MODEL_STD: template = model["tmpls"][data[4]] else: template = model["tmpls"][0] flag = data[7] deck_id = data[3] card_id = data[0] tags = data[5] qfmt = qfmt or template["qfmt"] afmt = afmt or template["afmt"] # create map of field names -> field content fields: Dict[str, str] = {} for (name, (idx, conf)) in list(self.models.fieldMap(model).items()): fields[name] = split_fields[idx] # add special fields fields["Tags"] = tags.strip() fields["Type"] = model["name"] fields["Deck"] = self.decks.name(deck_id) fields["Subdeck"] = fields["Deck"].split("::")[-1] fields["Card"] = template["name"] fields["CardFlag"] = self._flagNameFromCardFlags(flag) fields["c%d" % (card_ord + 1)] = "1" # legacy hook fields = runFilter("mungeFields", fields, model, data, self) ctx = TemplateRenderContext(self, data, fields) # render fields. if any custom filters are encountered, # the field_filter hook will be called. try: qtext, atext = render_card(self, qfmt, afmt, ctx) except anki.rsbackend.BackendException as e: errmsg = _("Card template has a problem:") + f"<br>{e}" qtext = errmsg atext = errmsg # avoid showing the user a confusing blank card if they've # forgotten to add a cloze deletion if model["type"] == MODEL_CLOZE: if not self.models._availClozeOrds(model, data[6], False): qtext = (qtext + "<p>" + _( "Please edit this note and add some cloze deletions. (%s)") % ("<a href=%s#cloze>%s</a>" % (HELP_SITE, _("help")))) # allow add-ons to modify the generated result (qtext, atext) = hooks.card_did_render((qtext, atext), ctx) # legacy hook qtext = runFilter("mungeQA", qtext, "q", fields, model, data, self) atext = runFilter("mungeQA", atext, "a", fields, model, data, self) return dict(q=qtext, a=atext, id=card_id)