gregorias / anki-code-highlighter

Anki plugin for code syntax highlighting.
GNU Affero General Public License v3.0
55 stars 3 forks source link

C++ code shown in a single line (AnkiDroid) #29

Closed pedy closed 1 year ago

pedy commented 1 year ago

A multi-line C++ code block (with <pre>) which was fine in the desktop version, was shown in a single line in AnkiDroid (previewing in Card Browser).

gregorias commented 1 year ago

Could you share the HTML code for the card?

pedy commented 1 year ago

Sure. This is before applying the plugin button:

<code><pre>int globalvar = 20;<br>int&amp; foo(){<br>    return globalvar;<br>}<br>int main(){<br>    foo() = 10;<br>    return 0;<br>}</pre></code>Here foo returns a reference, <em>which is an lvalue</em>, so it can be assigned to.<br><br>Also,<br>The assignment <code>mymap[10]</code> works because the non-const overload of <code>std::map::operator[]</code> returns a reference that can be assigned to.<br>

P.S. I'm not sure this was before it. I know that I hit CTRL-Z for undo until I reached the status before applying, but there were a few synchronizations. So if you couldn't reproduce the issue with this HTML, tell me; Maybe I should roll-back to a backup.

gregorias commented 1 year ago

You should not add your own code annotations before applying the plugin. Here's what you need to do to fix this:

  1. Remove <code><pre> tags. This should be the result:
    int globalvar = 20;<br>int&amp; foo(){<br>    return globalvar;<br>}<br>int main(){<br>    foo() = 10;<br>    return 0;<br>}
    Here foo returns a reference, <em>which is an lvalue</em>, so it can be assigned to.<br><br>Also,<br>The assignment <code>mymap[10]</code> works because the non-const overload of <code>std::map::operator[]</code> returns a reference that can be assigned to.<br>
  2. Select the code block with your mouse: image
  3. Run the plugin's action (e.g., with the keyboard shortcut, CTRL+').

This should be the result:

<pre style="display:flex; justify-content:center;"><code class="language-cpp">int globalvar = 20;
int&amp; foo(){
    return globalvar;
}
int main(){
    foo() = 10;
    return 0;
}</code></pre>
Here foo returns a reference, <em>which is an lvalue</em>, so it can be assigned to.<br><br>Also,<br>The assignment <code>mymap[10]</code> works because the non-const overload of <code>std::map::operator[]</code> returns a reference that can be assigned to.
image
pedy commented 1 year ago

Thanks for the reproduction and the detailed explanation. As I mentioned, I didn't have any issues on the desktop version. The problem was happening in AnkiDroid and

My code block already had <pre> and <code> pairs. Removing them and leaving only what the add-on had added, didn't solve the issue either.

gregorias commented 1 year ago

Could you share following:

  1. The source code of the buggy card that is on the Android device
  2. A screenshot of the buggy card

Have you synced databases? The issue could be that the card on android didn't actually receive the proper HTML with a single pair of <pre><code> tags.

pedy commented 1 year ago

I did it again right now. I removed my own <pre> and <code> tags, then applied the add-on button. Yes, I synced both times and checked the HTML source of the card in Android. It's the same result.

HTML Code:

<pre style="display:flex; justify-content:center;"><code class="language-cpp">int globalvar = 20;
int&amp; foo(){
    return globalvar;
}
int main(){
    foo() = 10;
    return 0;
}</code></pre><br>Here foo returns a reference, <em>which is an lvalue</em>, so it can be assigned to.<br><br>Also,<br>The assignment <code>mymap[10]</code> works because the non-const overload of <code>std::map::operator[]</code> returns a reference that can be assigned to.<br><br>

Screenshots of Android: view source

Screenshots of the desktop version: Screenshot_20221229_220625 Screenshot_20221229_220642

gregorias commented 1 year ago

I see. My guess here is that something is hardcoding the value of white-space in your mobile styles.

You can verify that by overriding any global settings with <pre style="display:flex; justify-content: center; white-space:pre;"><code class="language-cpp" style="white-space:pre;"> (adding white-space:pre to containers).

If that's the case, perhaps double check your card templates if there's nothing that overrides that style attribute?

If that doesn't help, could you try and create a reproducible case by starting from a fresh profile (which shouldn't have this issue) and letting me know how I can reproduce this?

pedy commented 1 year ago

I figured out one thing and faced a new issue!

  1. The problem was in the preview of AnkiDroid card browser. (In my own profile, I couldn't wait until review time of the edited card, so I was checking it in card browser, both on desktop and Android. The desktop was fine, the Android wasn't.) Trying to reproduce in an empty deck, the test card was the only card and I could easily open it to review; the display in review was fine (multi-line).
  2. I added a new line of code (another C++ statement) by hitting enter in Android keyboard, but it messed the card again, even in the review mode! (So yes, in addition to difference between card browser and review behavior, it might be related to how AnkiDroid works with new line.

Anyway, to document what I did:

What do you suggest? Reporting the issue to AnkiDroid? If yes, please describe your technical perception from the situation.

Note: It's all over the web that AnkiDroid doesn't support multiple profiles, but you can install different versions from Google Play and GitHub. I couldn't; all of them was replacing one another. So I had to go that extra mile of deleting my AnkiDroid data.

gregorias commented 1 year ago

Thanks for the in-depth write-up. The good news is that I can reproduce this issue reliably and was able to hone down on the root cause.

Here's what I propose could work for you:

  1. If you need to use card browser preview, use pygments as the highlighter. Otherwise, avoid the preview.
  2. Do not edit code cards in AnkiDroid.

Ad 1. The hljs highlighter uses a JavaScript script, and the script somehow causes this behavior. AnkiDroid's preview is doing something wonky (you shouldn't render the same card in two different ways) and the most expedient way to mitigate this is to avoid the functionality. Either do not use the hljs highlighter or the preview. AnkiDroid has over 300 open issues. I don't see it likely that they'll fix an obscure rendering mismatch such as this. Ad 2. AnkiDroid's editing functionality replaces newlines with <br>, which breaks preformatting. I just avoid using it and edit on desktop.

Wide lines work just fine: the code blocks become scrollable.

pedy commented 1 year ago

I personally prefer to go on with hljs, because I want my notes as intact as possible; Pygments makes a mess! :D

Although I don't want to rely on Pygments, I saw an issue that I reported as #31 . Thanks for the project and dedication.

pedy commented 1 year ago

For the record, I just saw this in AnkiDroid advanced settings: Screenshot_20230104_150806_com ichi2 anki_edit_1002973181701640 The point is that AnkiDroid does not have separate HTML and web/rich editors (probably due to screen size limitation on phones), so it has chosen the HTML as the fundamental one, and has "facilitated" editing by this option.

gregorias commented 1 year ago

For the record, I just saw this in AnkiDroid advanced settings: Screenshot_20230104_150806_com ichi2 anki_edit_1002973181701640 The point is that AnkiDroid does not have separate HTML and web/rich editors (probably due to screen size limitation on phones), so it has chosen the HTML as the fundamental one, and has "facilitated" editing by this option.

Thanks, I wasn't aware of that.