[UserScript] Advanced Context Sentence

it’s my specialty, fixing bugs by just getting them reported :laughing:

3 Likes

Hi, awesome script! Although I get this whenever I try to pull context sentences during reviews.

I only get this glitch when I am doing reviews. Its actually fine when I am looking up words in the word lookup in wanikani, and I am not sure about lessons (I’ll check next time I get vocab in lessons). Just in case, I do have Wanikani Open Framework JLPT, Joyo, and Frequency filters, as well as I am running Hide Context Sentences and Move Context Sentences to the Top. Another thing to note is that I am running a third party dark mode chrome extension that works on all sites. If this could be solved, thatd be great! Cheers!

1 Like

This script is not active on the preview site

2 Likes

The issue which @baumkuchen reported a few months back still appears to be, well, an issue.
Also only seeing this during reviews.

@Kumirei as I saw you posting here I was wondering if you might take a look to find out why this script is dishing out gibberish during reviews.

Totally tell me to sod off if you’d like to :wink: I’d totally understand LOL

(Edit: Or know a man who can :wink: … although that’s prolly you too)

The problem is that the Advanced Context Sentence script modifies every example sentence that gets added to the page. Normally, this is no problem, but if you use the “Move Context Sentences to the Top” userscript, then the modifications get applied twice: once for the first time the sentences are added to the page, and the second time when they are removed and re-inserted at the top.

One possible fix would be to search the Advanced Context Sentence script for this line:

const sentences = document.querySelectorAll(".context-sentence-group");

and replace it with:

const sentences = document.querySelectorAll(".context-sentence-group:not(.advanced)");
sentences.forEach(s => s.classList.add("advanced"));
2 Likes

mfw my script is the culprit

1 Like

Yes, on the ball, indeed disabling this script resolved it.

@Kumirei funny that aye. Of-course I was using that script, probably, because you made it. You want to tweak it to make these two work together or shall I just apply the suggestion @Sinyaven kindly suggested above?

1 Like

I think the Advanced Context Sentence script is the more appropriate place to fix this incompatibility. @Kumirei’s script does nothing wrong, and could probably only “solve” this with an extremely ugly hack (instead of removing and re-inserting the context sentence section at the top, they could shift the visual output of the section with CSS by the appropriate amount of pixels upwards and the other elements downwards; ew – I feel filthy just for typing out this approach ^^).

2 Likes

I agree that this script should be altered to be more robust, but just as a theoretical: how about just making the info box a flexbox and setting the context sentence’s order to 0?

2 Likes

You are right, I hadn’t thought of that. This seems like a good idea.

Maybe using a CSS grid would be even better? This would allow to replicate the 40px margin between the sections using row-gap: 40px, which is probably cleaner than changing the margin-bottom of :last-child back to 40px and of nth-last-child(2) to 0.

// ==UserScript==
// @name         Wanikani: Move context sentence to top
// @namespace    http://tampermonkey.net/
// @version      0.1.2
// @description  Moves the context sentence to the top when you open the full info of a vocabulary item.
// @author       Kumirei
// @include      *wanikani.com/review/session
// @include      *preview.wanikani.com/review/session
// @grant        none
// ==/UserScript==

(function() {
	let style = document.createElement("style");
	style.innerText = "#item-info-col2 { display: inline-grid; row-gap: 40px; }" +
		"#item-info #item-info-col2 section, #item-info-col2 section *:last-child { margin-bottom: 0; }" +
		"#item-info-context-sentences { order: -1; }";
	document.head.appendChild(style);
})();

I also found another bug while testing: The Advanced Context Sentence script thinks that 叩 is not on WaniKani. It seems that using your JLPT, Joyo, and Frequency filters reduces the results of wkof.ItemData.get_items:

let items = await wkof.ItemData.get_items({wk_items: {options: {assignments: true}, filters: {item_type: ["kan"]}}});
// items.length === 2048
let items = await wkof.ItemData.get_items({wk_items: {options: {assignments: true}, filters: {item_type: ["kan"], include_frequency_data: true}}});
// items.length === 2026

Is this the intended behavior?

Sounds good to me!

I don’t think it is, but I would have to take a closer look to be sure, haha. I’ll have a look at both things tomorrwo

1 Like

It was not! Thanks for noticing. There was a silent error for items not in the data set and it never got to the return statement for those items. Just had to insert a conditional.

1 Like

Thanks @Kumirei for the silent fix.
It works fine here now.

3 Likes

Any idea why this becomes broken when using Stroke Order Diagram?

Is anyone else seeing a resource leak when using this script in lessons?

  1. Set lesson batch size to 6.
  2. Do two batches of 6 vocab lessons each directly back to back without going to the review summary page in between.
  3. About halfway through the second batch, memory usage starts to climb by an additional 25-100mb and the webpage becomes much less responsive

This happens reliably for me even if this is the only script enabled, and does not happen when I disable this script, no matter what other scripts I have running.

other possibly relevant details: I use the keyboard for navigation in lessons. This issue only happens with vocab lessons, not kanji / radicals.

1 Like

I found the issue and have put a patch below. @abdullahalt could you incorporate the fix?

The main cause seems to be that after finishing the lesson quiz, there will always be context sentences from the quiz info box still present but hidden. These sentences are repeatedly parsed and rewritten by Advanced Context Sentence. Also, there was an issue with tippy instances not being destroyed in certain scenarios and parseHTML being used which seemed to contribute to the problem. The patch below fixes these issues and an issue with JLPT filters not being detected due to a change in the JLPT filters script.

@@ -3,15 +3,15 @@
 // ==UserScript==
 // @name         Advanced Context Sentence
 // @namespace    https://openuserjs.org/users/abdullahalt
-// @version      1.40
+// @version      1.41
 // @description  Enhance the context sentence section, highlighting kanji and adding audio
 // @author       abdullahalt
 // @match        https://www.wanikani.com/lesson/session
 // @match        https://www.wanikani.com/review/session
 // @match        https://www.wanikani.com/vocabulary/*
+// @require      https://unpkg.com/@popperjs/core@2.5.4/dist/umd/popper.min.js
+// @require      https://unpkg.com/tippy.js@6.2.7/dist/tippy-bundle.umd.min.js
 // @grant        none
-// @require      https://unpkg.com/popper.js@1/dist/umd/popper.min.js
-// @require      https://unpkg.com/tippy.js@4
 // @copyright    2019, abdullahalt (https://openuserjs.org//users/abdullahalt)
 // @license MIT
 // ==/UserScript==
@@ -162,21 +162,23 @@

     if (wkof) evolveHeader(getHeader(sentences));

-    sentences.forEach(sentence => {
+    sentences.forEach(function(sentence) {
       const japaneseSentence = sentence.querySelector('p[lang="ja"]');
-      const audioButton = createAudioButton(japaneseSentence.innerHTML);
+      // without below, it might try to evolve hidden context sentences from quiz during a second lesson batch causing
+      // resource leak
+      if (japaneseSentence.childNodes.length != 1 || japaneseSentence.childNodes[0].nodeType != Node.TEXT_NODE) {
+          return;
+      }
+      let sentenceText = japaneseSentence.childNodes[0].nodeValue;
+      const audioButton = createAudioButton(sentenceText);
       //let advancedExampleSentence = "";
-      const chars = japaneseSentence.innerHTML.split("");
-      japaneseSentence.innerHTML = "";
-      chars.forEach(char => {
-        japaneseSentence.innerHTML =
-          japaneseSentence.innerHTML + tagAndLinkKanji(char).trim();
-      });
-
-      highlightKanji();
-
+      const chars = sentenceText.split("");
+      let newNodes = chars.map(char => tagAndLinkKanji(char));
+      japaneseSentence.replaceChildren(...newNodes);
       japaneseSentence.append(audioButton);
     });
+
+    highlightKanji();
   }

   function evolveHeader(header) {
@@ -383,7 +385,7 @@
   }

   function tagAndLinkKanji(char) {
-    return isKanji(char) ? wrapInAnchor(char).outerHTML : char;
+    return isKanji(char) ? wrapInAnchor(char) : document.createTextNode(char);
   }

   /**
@@ -528,7 +530,7 @@
       item_type: ["kan"]
     };

-    if (wkof.get_state("wkof.Kumirei.JJFFilters") === "ready") {
+    if (wkof.get_state("JJFFilters") === "ready") {
       state.jiff = true;
       filters.include_frequency_data = true;
       filters.include_jlpt_data = true;
@@ -590,6 +592,7 @@
     return source;
   }

+  let tippys = new Set();
   function highlightKanji() {
     const rules = document.querySelector("#acs-style").sheet.cssRules;
     rules[0].style.color = state.settings.recognizedKanjiColor;
@@ -597,6 +600,9 @@

     if (!wkof) return;

+    tippys.forEach(t => t.destroy());
+    tippys = new Set();
+
     const anchors = document.querySelectorAll(".context-sentence-group a");
     anchors.forEach(anchor => {
       const srs = anchor.getAttribute("data-srs");
@@ -604,22 +610,21 @@

       if (srs >= state.settings.recognitionLevel)
         anchor.setAttribute("class", "recognized");
-      else {
+      else
         anchor.setAttribute("class", "unrecognized");
-      }

-      if (anchor._tippy) anchor._tippy.destroy();
       if (state.settings.tooltip.show) {
         const kanji = state.kanjis.find(item => item.char == char);
         const tooltip = createTooltip(kanji);

         tippy(anchor, {
-          content: tooltip.outerHTML,
+          content: tooltip,
           size: "small",
           arrow: true,
           placement: state.settings.tooltip.position,
           delay: [state.settings.tooltip.delay, 20]
         });
+        tippys.add(anchor._tippy);
       }
     });
   }
1 Like

I don’t know if anyone is having the same issue but about 2 days ago the script doesn’t seem to work when I’m doing lessons and on the context tab.

It does work when I’m doing reviews and checking the sentences there. Is it because the sentences are displayed on the same screen unlike the lessons which are now in 4 different tabs?

1 Like

Yeah, I’m having the same issue. It’s not just you. :slight_smile:

1 Like