// ==UserScript== // @name WaniKani Unobtrusive Kanji Stroke Order // @namespace org.atzkey // @version 1.4.1 // @description An unobtrusive Kanji Stroke Order display for WaniKani // @author atzkey // // @match https://*.wanikani.com/kanji/* // @match https://wanikani.com/kanji/* // // @match https://*.wanikani.com/vocabulary/* // @match https://wanikani.com/vocabulary/* // // @match https://*.wanikani.com/subjects/*/lesson* // @match https://wanikani.com/subjects/*/lesson* // @run-at document-idle // @grant none // @downloadURL https://update.greasyfork.icu/scripts/36825/WaniKani%20Unobtrusive%20Kanji%20Stroke%20Order.user.js // @updateURL https://update.greasyfork.icu/scripts/36825/WaniKani%20Unobtrusive%20Kanji%20Stroke%20Order.meta.js // ==/UserScript== (function() { 'use strict'; const ksoFont = 'KanjiStrokeOrders'; const ksoStyle = document.createElement('style'); ksoStyle.innerHTML = ` .page-header__icon--kanji:hover, .page-header__icon--vocabulary:hover { font-family: "${ksoFont}"; font-weight: normal; } .character-header__characters.kso { font-family: "${ksoFont}"; font-weight: normal; } `; const lessonCharacterSelector = '.character-header__characters'; function wkAlert(text) { const search = document.getElementById('search'); const anchor = search.parentNode; let alert = document.createElement('div'); alert.className = 'alert alert-error fade in'; alert.innerHTML = ` x ${text} `; anchor.insertBefore(alert, search); } function isFontAvailable(fontName) { let canvas = document.createElement("canvas"); canvas.width = 1000; let context = canvas.getContext("2d"); // the text whose final pixel size I want to measure let text = "Font availability detection, 0123456789!?."; let checks = ['monospace', 'sans-serif', 'serif'].map((fontFamily) => { // specifying the baseline font context.font = "72px " + fontFamily; // checking the size of the baseline text let baselineSize = context.measureText(text).width; // specifying the font whose existence we want to check context.font = "72px '" + fontName + "', " + fontFamily; // checking the size of the font we want to check let newSize = context.measureText(text).width; return newSize !== baselineSize; }); return checks.find((x) => x); } function handleLessonKsoToggle(e) { e.target.classList.toggle('kso'); } if (isFontAvailable(ksoFont)) { let head = document.getElementsByTagName('head')[0]; head.appendChild(ksoStyle); let observer = new MutationObserver(function(mutations) { const character = document.querySelector(lessonCharacterSelector); if (character) { character.addEventListener('click', handleLessonKsoToggle); observer.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true }); } else { wkAlert(`Download and install Kanji Stroke Order font.`); } })();