mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
if latex fails to render in bulk, show the user the problem
This commit is contained in:
parent
9df2a08cb0
commit
2d0499580f
3 changed files with 41 additions and 10 deletions
|
@ -7,7 +7,7 @@ import html
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
from typing import Any, Optional
|
from typing import Any, List, Optional, Tuple
|
||||||
|
|
||||||
import anki
|
import anki
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
|
@ -48,11 +48,24 @@ def on_card_did_render(output: TemplateRenderOutput, ctx: TemplateRenderContext)
|
||||||
|
|
||||||
def render_latex(html: str, model: NoteType, col: anki.storage._Collection,) -> str:
|
def render_latex(html: str, model: NoteType, col: anki.storage._Collection,) -> str:
|
||||||
"Convert TEXT with embedded latex tags to image links."
|
"Convert TEXT with embedded latex tags to image links."
|
||||||
|
html, err = render_latex_returning_errors(html, model, col)
|
||||||
|
if err:
|
||||||
|
html += "\n".join(err)
|
||||||
|
return html
|
||||||
|
|
||||||
|
|
||||||
|
def render_latex_returning_errors(
|
||||||
|
html: str, model: NoteType, col: anki.storage._Collection
|
||||||
|
) -> Tuple[str, List[str]]:
|
||||||
|
"""Returns (text, errors).
|
||||||
|
|
||||||
|
error_message will be non-empty is LaTeX failed to render."""
|
||||||
svg = model.get("latexsvg", False)
|
svg = model.get("latexsvg", False)
|
||||||
header = model["latexPre"]
|
header = model["latexPre"]
|
||||||
footer = model["latexPost"]
|
footer = model["latexPost"]
|
||||||
|
|
||||||
out = col.backend.extract_latex(html, svg)
|
out = col.backend.extract_latex(html, svg)
|
||||||
|
errors = []
|
||||||
html = out.html
|
html = out.html
|
||||||
|
|
||||||
for latex in out.latex:
|
for latex in out.latex:
|
||||||
|
@ -62,9 +75,9 @@ def render_latex(html: str, model: NoteType, col: anki.storage._Collection,) ->
|
||||||
|
|
||||||
err = _save_latex_image(col, latex, header, footer, svg)
|
err = _save_latex_image(col, latex, header, footer, svg)
|
||||||
if err is not None:
|
if err is not None:
|
||||||
html += err
|
errors.append(err)
|
||||||
|
|
||||||
return html
|
return html, errors
|
||||||
|
|
||||||
|
|
||||||
def _save_latex_image(
|
def _save_latex_image(
|
||||||
|
|
|
@ -13,7 +13,7 @@ from typing import Any, Callable, List, Optional, Tuple, Union
|
||||||
|
|
||||||
import anki
|
import anki
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.latex import render_latex
|
from anki.latex import render_latex, render_latex_returning_errors
|
||||||
from anki.rsbackend import MediaCheckOutput
|
from anki.rsbackend import MediaCheckOutput
|
||||||
from anki.utils import intTime
|
from anki.utils import intTime
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@ def media_paths_from_col_path(col_path: str) -> Tuple[str, str]:
|
||||||
# fixme: look into whether we can drop chdir() below
|
# fixme: look into whether we can drop chdir() below
|
||||||
# - need to check aa89d06304fecd3597da4565330a3e55bdbb91fe
|
# - need to check aa89d06304fecd3597da4565330a3e55bdbb91fe
|
||||||
# - and audio handling code
|
# - and audio handling code
|
||||||
|
|
||||||
|
|
||||||
class MediaManager:
|
class MediaManager:
|
||||||
|
|
||||||
soundRegexps = [r"(?i)(\[sound:(?P<fname>[^]]+)\])"]
|
soundRegexps = [r"(?i)(\[sound:(?P<fname>[^]]+)\])"]
|
||||||
|
@ -164,11 +166,15 @@ class MediaManager:
|
||||||
"This should be called while the collection is closed."
|
"This should be called while the collection is closed."
|
||||||
return self.col.backend.check_media()
|
return self.col.backend.check_media()
|
||||||
|
|
||||||
def render_all_latex(self, progress_cb: Optional[Callable[[int], bool]] = None):
|
def render_all_latex(
|
||||||
|
self, progress_cb: Optional[Callable[[int], bool]] = None
|
||||||
|
) -> Optional[Tuple[int, str]]:
|
||||||
"""Render any LaTeX that is missing.
|
"""Render any LaTeX that is missing.
|
||||||
|
|
||||||
If a progress callback is provided and it returns false, the operation
|
If a progress callback is provided and it returns false, the operation
|
||||||
will be aborted.
|
will be aborted.
|
||||||
|
|
||||||
|
If an error is encountered, returns (note_id, error_message)
|
||||||
"""
|
"""
|
||||||
last_progress = intTime()
|
last_progress = intTime()
|
||||||
for c, (nid, mid, flds) in enumerate(
|
for c, (nid, mid, flds) in enumerate(
|
||||||
|
@ -178,14 +184,18 @@ class MediaManager:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
model = self.col.models.get(mid)
|
model = self.col.models.get(mid)
|
||||||
render_latex(flds, model, self.col)
|
_html, errors = render_latex_returning_errors(flds, model, self.col)
|
||||||
|
if errors:
|
||||||
|
return (nid, "\n".join(errors))
|
||||||
|
|
||||||
if c % 10 == 0:
|
if c % 10 == 0:
|
||||||
elap = last_progress - intTime()
|
elap = last_progress - intTime()
|
||||||
if elap >= 1 and progress_cb is not None:
|
if elap >= 1 and progress_cb is not None:
|
||||||
last_progress = intTime()
|
last_progress = intTime()
|
||||||
if not progress_cb(c + 1):
|
if not progress_cb(c + 1):
|
||||||
return
|
return None
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
# Legacy
|
# Legacy
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
|
@ -14,7 +14,7 @@ from anki import hooks
|
||||||
from anki.lang import _, ngettext
|
from anki.lang import _, ngettext
|
||||||
from anki.rsbackend import Interrupted, MediaCheckOutput, Progress, ProgressKind
|
from anki.rsbackend import Interrupted, MediaCheckOutput, Progress, ProgressKind
|
||||||
from aqt.qt import *
|
from aqt.qt import *
|
||||||
from aqt.utils import askUser, restoreGeom, saveGeom, tooltip
|
from aqt.utils import askUser, restoreGeom, saveGeom, showText, tooltip
|
||||||
|
|
||||||
|
|
||||||
def check_media_db(mw: aqt.AnkiQt) -> None:
|
def check_media_db(mw: aqt.AnkiQt) -> None:
|
||||||
|
@ -97,10 +97,18 @@ class MediaChecker:
|
||||||
def _on_render_latex(self):
|
def _on_render_latex(self):
|
||||||
self.progress_dialog = self.mw.progress.start()
|
self.progress_dialog = self.mw.progress.start()
|
||||||
try:
|
try:
|
||||||
self.mw.col.media.render_all_latex(self._on_render_latex_progress)
|
out = self.mw.col.media.render_all_latex(self._on_render_latex_progress)
|
||||||
finally:
|
finally:
|
||||||
self.mw.progress.finish()
|
self.mw.progress.finish()
|
||||||
tooltip(_("LaTeX rendered."))
|
|
||||||
|
if out is not None:
|
||||||
|
nid, err = out
|
||||||
|
browser = aqt.dialogs.open("Browser", self.mw)
|
||||||
|
browser.form.searchEdit.lineEdit().setText("nid:%d" % nid)
|
||||||
|
browser.onSearchActivated()
|
||||||
|
showText(err, type="html")
|
||||||
|
else:
|
||||||
|
tooltip(_("All LaTeX rendered."))
|
||||||
|
|
||||||
def _on_render_latex_progress(self, count: int) -> bool:
|
def _on_render_latex_progress(self, count: int) -> bool:
|
||||||
if self.progress_dialog.wantCancel:
|
if self.progress_dialog.wantCancel:
|
||||||
|
|
Loading…
Reference in a new issue