Anki-android: Ankidroid - Anki 2.1 - Mathjax

Created on 19 Aug 2018  路  36Comments  路  Source: ankidroid/Anki-Android

Research

Enter an [ x ] character to confirm the points below:

[X] I have read the support page and am reporting a bug or enhancement request specific to AnkiDroid

[X] I have checked the manual and the FAQ and could not find a solution to my issue

[X] I have searched for similar existing issues here and on the user forum

Reproduction Steps
  1. start anki desktop create mathjax card /( 1+1 /)
  2. on anki desktop ist beautiful 1+1
  3. on ankidroid still /( 1+1 /)
Expected Result

it should make inline formula like old latex pictures only with vectorgraphics

Actual Result

only code

Debug info

Refer to the support page if you are unsure where to get the "debug info".

Accepted Enhancement Priority-Medium

Most helpful comment

Thanks for the comments, @mikehardy.

I just managed to get MathJax, Anki 2.1, and AnkiDroid all playing nicely together. The key was adding an extra backslash in my note template, like so:

{{cloze:Text}}
<script type="text/x-mathjax-config">
    MathJax.Hub.processSectionDelay = 0;
    MathJax.Hub.Config({
        messageStyle:"none",
        showProcessingMessages:false,
        tex2jax:{
            inlineMath: [ ['$','$'], ['\\(','\\)'] ],
            displayMath: [ ['$$','$$'], ['\\[','\\]'] ],
            processEscapes:true
        }
});
</script>
<script type="text/javascript">
(function() {
  if (window.MathJax != null) {
    var card = document.querySelector('.card');
    MathJax.Hub.Queue(['Typeset', MathJax.Hub, card]);
    return;
  }
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS_SVG-full';
  document.body.appendChild(script);
})();
</script>

Now LaTeX displays correctly in both Anki 2.1 and AnkiDroid.

All 36 comments

Here is the relevant part of the manual: https://apps.ankiweb.net/docs/manual.html#mathjax-support

Here's standard use of MathJax in Android:
https://github.com/mathjax/MathJax-docs/wiki/Guide:-MathJax-in-Android-apps

...but here's the upstream version in Python (and JS/CSS for MathJax) as a base for any port:
https://github.com/dae/anki/tree/master/web/mathjax

(You can see the evolution of the implementation this way - it's not too crazy)

Integrating it just enough to display cards correctly during review would be the natural first step.

It appears that a zip of the mathjax-related portions of AnkiDesktop is 792K, vs a current AnkiDroid debug APK of around 9MB, so this will increase APK size about 10% to support it in the same way as AnkiDesktop at a first glance

As a side note, I didn't see anything else besides the V2 scheduler (already noted in #4905) in v2.1+ but I could be missing something

If anyone has a good sample deck (especially with clozures in it) that would be helpful to link directly or attach, as edge cases may be difficult

As a side note, I didn't see anything else besides the V2 scheduler (already noted in #4905) in v2.1+ but I could be missing something

There are minor changes to the sync protocol regarding deletions, but the old way seems to be still supported for now: https://github.com/dae/anki/commit/eb44584b290181e0397a231e6291ca36b86d4189

@tsudoko - thanks for the pointer! Looks like they send up to 250 deletes at a time now, whereas we already batch all deletes in one big JSONObject and punch it in one shot. For most other things to sync we also do it in one shot, then for notes cards and reviews we chunk it 250 a time if I'm reading right, so I think we're okay there.

Scheduler v2 and MathJax are big items though.

If anyone has a good sample deck (especially with clozures in it) that would be helpful to link directly or attach, as edge cases may be difficult

Do you still need a sample deck?

@Moosehorse123 Yes!

@Moosehorse123 Yes!

Ok! I have plenty deck options, let me know what specifications that you require other than cloze cards. Also does your listed email address work to send it to?

I don't have exact specifications, just something that would be good as a verifier to make sure everything worked. So if there are mathjax expressions that are rare + difficult, then those. And integrating cloze and mathjax (with overlaps if Anki Desktop supports it) is important to make sure we handle that correctly - it looked like the hardest part of the Anki Desktop implementation. Other than that, just not too big - shouldn't need more than a few cards I think? And my preference would be to have it attached here so anyone could use it if they started work. Thanks!

I was able to get a workaround going with Anki 2.0 (on Mac desktop) and $ and $$ as delimiters. This worked properly on AnkiDroid (though it was a bit slow to render). This was the template I used:

{{cloze:Text}}
<script type="text/x-mathjax-config">
    MathJax.Hub.processSectionDelay = 0;
    MathJax.Hub.Config({
        messageStyle:"none",
        showProcessingMessages:false,
        tex2jax:{
            inlineMath: [['$','$']],
            displayMath:[['$$','$$']],
            processEscapes:true
        }
});
</script>
<script type="text/javascript">
(function() {
  if (window.MathJax != null) {
    var card = document.querySelector('.card');
    MathJax.Hub.Queue(['Typeset', MathJax.Hub, card]);
    return;
  }
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS_SVG-full';
  document.body.appendChild(script);
})();
</script>

Now that I've started using 2.1 (along with the built-in delimiters \( \) and [ ]), MathJax is no longer rendered. I tried updating the note template with the new delimiters, but it didn't seem to have an effect.

Is there any workaround for this right now?

As for the sample deck, here's one of mine with MathJax, Cloze deletions, basic cards, etc.

https://www.dropbox.com/s/epw3qbg8limlmip/LinearAlgebraDeck.apkg?dl=0

Unfortunately no workaround that I know of but I'm pretty impressed you managed it with 2.0 - that's a nice bit of code. It's my understanding that all the AbstractFlashcardReviewer/TemplateEditor code would need a look for this to be complete, but that simply including the MathJax distribution in Anki and referencing it in an rendering hook like LaTeX did might be enough to get rendering working

Thanks very much for the deck, even though memories of linear algebra class make me shudder :-). Not my finest class. I'm attaching it directly here so it doesn't disappear

LinearAlgebraDeck.apkg.zip

Should've just zipped it, thanks.

That LaTeX class just displays LaTeX images, correct? For how Anki used to handle LaTeX?

I'd love to dig into this but should probably try my hand at a simpler item first. It's been a long time since I've done anything with Java/Android.

As for the workaround, I feel like if it were working under 2.0 then getting it going with 2.1 shouldn't be too onerous.

That LaTeX class just displays LaTeX images, correct? For how Anki used to handle LaTeX?

True, but it does this relatively simple task through the external render hooks infrastructure, which if I'm understanding correctly gives the full HTML contents of the card to each hook in turn and lets them do whatever they want with it. So you could look for the new delimiters via regex and rewrite it with whatever javascript was needed to reference the MathJax package (which should be in-app / local, IMHO but could be referenced by CDN like you did to start)

I'd love to dig into this but should probably try my hand at a simpler item first. It's been a long time since I've done anything with Java/Android.

I think a full-fledged implementation (like where AnkiDesktop doesn't highlight cloze when mathjax is present) is pretty tightly coupled and thus more difficult, but giving it a whirl with an external hook might actually be a quick win. Or at least a time-boxed test :-)

As for the workaround, I feel like if it were working under 2.0 then getting it going with 2.1 shouldn't be too onerous.

Because all the heavy-lifting is in Javascript we would just bundle (or reference, as you did) while the on-device webview does the work, I agree it should be almost trivial.

Thanks for the comments, @mikehardy.

I just managed to get MathJax, Anki 2.1, and AnkiDroid all playing nicely together. The key was adding an extra backslash in my note template, like so:

{{cloze:Text}}
<script type="text/x-mathjax-config">
    MathJax.Hub.processSectionDelay = 0;
    MathJax.Hub.Config({
        messageStyle:"none",
        showProcessingMessages:false,
        tex2jax:{
            inlineMath: [ ['$','$'], ['\\(','\\)'] ],
            displayMath: [ ['$$','$$'], ['\\[','\\]'] ],
            processEscapes:true
        }
});
</script>
<script type="text/javascript">
(function() {
  if (window.MathJax != null) {
    var card = document.querySelector('.card');
    MathJax.Hub.Queue(['Typeset', MathJax.Hub, card]);
    return;
  }
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS_SVG-full';
  document.body.appendChild(script);
})();
</script>

Now LaTeX displays correctly in both Anki 2.1 and AnkiDroid.

Hey, that's fantastic and thanks for sharing the code so others can use it until it's built-in.

My pleasure. Hopefully I can find some time to dig into this myself.

Thanks for the comments, @mikehardy.

I just managed to get MathJax, Anki 2.1, and AnkiDroid all playing nicely together. The key was adding an extra backslash in my note template, like so:

{{cloze:Text}}
<script type="text/x-mathjax-config">
    MathJax.Hub.processSectionDelay = 0;
    MathJax.Hub.Config({
        messageStyle:"none",
        showProcessingMessages:false,
        tex2jax:{
            inlineMath: [ ['$','$'], ['\\(','\\)'] ],
            displayMath: [ ['$$','$$'], ['\\[','\\]'] ],
            processEscapes:true
        }
});
</script>
<script type="text/javascript">
(function() {
  if (window.MathJax != null) {
    var card = document.querySelector('.card');
    MathJax.Hub.Queue(['Typeset', MathJax.Hub, card]);
    return;
  }
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS_SVG-full';
  document.body.appendChild(script);
})();
</script>

Now LaTeX displays correctly in both Anki 2.1 and AnkiDroid.

This works great! Only issue if you have some maths that naturally includes }} because that gets interpreted as a cloze close.

e.g.
{{c1::\(\beta\)}} {{c2::\(\beta = \frac{\alpha}{\sum_{0}^{1}}\)}}

will give you

front
image
back
image

but if I add a space, going from {1}} to {1} } I get

front
image
back
image

in context

{{c1::\(\beta\)}} {{c2::\(\beta = \frac{\alpha}{\sum_{0}^{1} }\)}}

Thanks @alxmjo and @mikehardy with after reinstalling the apkg on the firetablet it works.

{{cloze:Text}}
<script type="text/x-mathjax-config">
    MathJax.Hub.processSectionDelay = 0;
    MathJax.Hub.Config({
        messageStyle:"none",
        showProcessingMessages:false,
        tex2jax:{
            inlineMath: [ ['$','$'], ['\\(','\\)'] ],
            displayMath: [ ['$$','$$'], ['\\[','\\]'] ],
            processEscapes:true
        }
});
</script>
<script type="text/javascript">
(function() {
  if (window.MathJax != null) {
    var card = document.querySelector('.card');
    MathJax.Hub.Queue(['Typeset', MathJax.Hub, card]);
    return;
  }
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS_SVG-full';
  document.body.appendChild(script);
})();
</script>

Now LaTeX displays correctly in both Anki 2.1 and AnkiDroid.

Am I missing something or does this no longer work?
I'm using this template for my cloze cards and it displays fine in Ankidroid, but on desktop (version 2.1.5 on Linux), it does not do anything and instead displays the source text, i.e. including the dollar signs. Are there any necessary settings I overlooked?

@jaspercpes I don't think the dollar signs are meant to be supported on the desktop client - the help docs mention that only \(, \) and \[, \] are supported, and these work for me on the desktop client and AnkiDroid with this workaround.

As just mentioned, this workaround works for me - I've been using it for a while now and the rendering is much nicer than with LaTeX.

A few points worth mentioning:

  • rendering is slower - an opened note will briefly show the markup before re-rendering the MathJax. I haven't seen this happen with the desktop client, so I presume some manner of pre-rendering happens there.
  • wide LaTeX image files get scaled down to fit the AnkiDroid screen - MathJax rendering goes off the side. I don't know whether this would be a bug or a feature :-) but the scaling was convenient, whereas I now have to be careful when creating cards to avoid having to scroll left/right.
  • perhaps most importantly from a compatibility point of view - with this workaround you can use MathJax inside a cloze deletion, but a cloze deletion inside a MathJax block will 'break' the rendering and just show the raw markup. The Anki desktop client renders this correctly with MathJax (and doing the same with LaTex worked fine, too).

@colinpretorius thanks for the feedback! We obviously hope to support mathjax natively but until then this is the only way to do it I'm aware of. Hopefully your info helps all that need mathjax until we get it Built-In

thanks to you i can now learn nice formulas on my e-book reader:
anki

EDIT: @alxmjo
so that the thread here does not pass the topic I have edited here.
Here you can find links with android ebook readers
https://blog.the-ebook-reader.com/2015/04/20/best-android-e-ink-ebook-readers-android-ereaders-list/
i have an onyx boox bought from aliexpress.
You can also root a Nook Simple Touch which is cheaper

@p3l4h0 Cool! Which e-reader is that?

Hi folks! Is this being worked on, and if not, does the approach planned in this thread still seem like a good idea?

@adamwolf hello! No, there is no current effort in progress for Mathjax - the javascript-based workaround is the only thing in action now. I outlined the full upstream change as a basis for a full implementation in AnkiDroid here https://github.com/ankidroid/Anki-Android/issues/4915#issuecomment-416692525 (above) and that was my best guess at the correct implementation at the time, I don't think anything should have changed.

Any ideas on how can we get Ankidroid to play nicely with mhchem?

I made some basic progress with this. There are some tricky things to be done with MathJax and clozes that I need to port tests over for, and see if I need to help make them pass.

The desktop client actually starts with the cards set invisible, and fades them in quickly after MathJax finishes the rendering of the math parts. I have recreated that as well. I'm certain there will be strong opinions on whether we should only do that on MathJax cards, or on all cards. I do not care either way, and it's easy to change.

@mikehardy (and anyone else appropriate) would you want me to copy in the MathJax stuff as a submodule or by just copying the files in and labeling what version they are or something else?

Awesome! And yes, the cloze looked the worst part of it

haha - people will scream if all cards fade. They may even prefer to do a placeholder + mathjax render unless the fade can be terminated as soon as mathjax is provably rendered. The userbase is very sensitive to even small lag on card review.

I believe Mathjax can be updated independently yes? Like, we want to have it local to save bandwidth etc, but it is conceivable the whole package - which comes from an outside source - might bump versions without us doing anything, just like a gradle dependency?

If I don't have that right please correct me, but if I do then I would like them as separate as possible, but in as close to their upstream format as possible, so that we can manage updates on the dependency easily.

You are correct regarding Mathjax upgrading without us having to do anything except a git pull and recompile. I will include instructions in a README alongside the external dependency.

Another option is to eliminate the fade completely. On non-Mathjax cards, keep it 100% exactly the same, and on Mathjax cards, snap the text in the moment Mathjax finishes. I suppose we could set it up so that the behavior is configurable via javascript variables, which users could set in their templates. In fact, this may be how desktop Anki is already set up. I will investigate.

I even have mhchem working.

Screenshot 2019-04-18 09 15 52

Oh that looks really nice! This is a popular feature request, it is going to help a lot of people I think.

Not to get offtopic, but I also need video stuff, so I'll be looking at that stuff next.

If you wanted to tackle the one everyone asks for, you could get #4756 in shape to merge - that one actually works, it's just moving the working functionality from the PR to a different style, or maybe @timrae will let this one in just for now to clear the queue pending an "advanced note editor" rework in the future. And not sure what you mean by video stuff but I'll always try to help if it is some bit of the code I know about. Cheers

Hey everyone! Go test the new releases I made here: https://github.com/mikehardy/Anki-Android/releases/tag/v2.9alpha69

They are parallel releases so they won't mess up your main install. But you can sync AnkiWeb or load apkg files or use them normally otherwise. The 2.9alpha69 release I just made has the current PR in it and I want some testing on it.

We understand the compatibility method described here does not work, but raw mathjax does work. If people could confirm that, and describe how difficult it is to revert the compatibility thing, I'd appreciate it. I would love to hear that it works, reverting the stopgap is easy, and we can merge this thing.

Cheers

@mikehardy So I installed your preview, and tried my cards on it. My MathJax cards work fine on this preview, even with the fix. The Anki test suite cards work fine. The Linear Algebra test deck renders fine, but it is not using the built-in Mathjax.

I'm feeling great about this.

Folks should remove the Compatibility stuff so that their Ankidroid isn't grabbing the external Mathjax all the time.

Well I'm just going to close this here issue right now ;-). It's merged! It's live!

Go grab your new alpha version folks, and stop using compatibility templates

Please raise new issues if you see them, but otherwise every time you use Mathjax in AnkiDroid spare a nice thought for @adamwolf - nice work, sir

Was this page helpful?
0 / 5 - 0 ratings