WaniKani Hide Context Sentence

Hide context sentences until hovered.

  1. // ==UserScript==
  2. // @name WaniKani Hide Context Sentence
  3. // @namespace rfindley
  4. // @description Hide context sentences until hovered.
  5. // @version 2.0.1
  6. // @match https://www.wanikani.com/*
  7. // @match https://preview.wanikani.com/*
  8. // @copyright 2015+, Robin Findley
  9. // @license MIT; http://opensource.org/licenses/MIT
  10. // @run-at document-start
  11. // @grant none
  12. // ==/UserScript==
  13.  
  14. (function(gobj) {
  15.  
  16. /* global app_load, page_load, before_page_render, frame_load, before_frame_render */
  17.  
  18. const match_patterns = [
  19. '/subjects/extra_study',
  20. '/subject-lessons/*',
  21. '/subjects/*/lesson',
  22. '/subjects/review',
  23. '/vocabulary/*'
  24. ];
  25. function url_matches(patterns,url) {patterns=patterns||match_patterns;url=url||window.location.pathname;if(url[0]!=='/')url=new URL(url).pathname;return ((Array.isArray(patterns)?patterns:[patterns]).findIndex((pattern)=>{let regex=new RegExp(pattern.replace(/[.+?^${}()|[\]\\]/g,'\\$&').replaceAll('*','.*'));return (regex.test(url));})>=0);}
  26. function is_turbo_page() {return (document.querySelector('script[type="importmap"]')?.innerHTML.match('@hotwired/turbo') != null);}
  27.  
  28. if (is_turbo_page()) {
  29. try {app_load();} catch(e){}
  30. try {document.documentElement.addEventListener('turbo:load', page_load);} catch(e){}
  31. try {document.documentElement.addEventListener('turbo:before-render', before_page_render);} catch(e){}
  32. try {document.documentElement.addEventListener('turbo:frame-load', frame_load);} catch(e){}
  33. try {document.documentElement.addEventListener('turbo:before-frame-render', before_frame_render);} catch(e){}
  34. } else {
  35. try {app_load();} catch(e){}
  36. try {page_load({detail:{url:window.location.href},target:document.documentElement});} catch(e){}
  37. try {frame_load({target:document.documentElement});} catch(e){}
  38. }
  39.  
  40. function app_load() {
  41. if (!url_matches()) return;
  42.  
  43. // Insert CSS
  44. document.head.insertAdjacentHTML('beforeend',`
  45. <style name="hide_context_sentence" type="text/css">
  46. .context-sentence-group p:not([lang="ja"]):not(:hover),
  47. .subject-collocations__collocation-text:not([lang="ja"]):not(:hover),
  48. .context-sentences .wk-text:not([lang="ja"]):not(:hover)
  49. {
  50. background-color:#ccc;
  51. color:#ccc;
  52. text-shadow:none;
  53. }
  54. </style>
  55. `);
  56. }
  57.  
  58. function page_load(e) { // e = {detail: {url: '...'}, target: <elem> }
  59. if (!url_matches()) return;
  60. add_new_context_sentences(e.target);
  61. }
  62.  
  63. function before_page_render(e) { // e = {detail: {newBody: <elem>} }
  64. if (!url_matches()) return;
  65. add_new_context_sentences(e.detail.newBody);
  66. }
  67.  
  68. function before_frame_render(e) { // e = {detail: {newFrame: <elem>} }
  69. if (!url_matches()) return;
  70. add_new_context_sentences(e.detail.newFrame);
  71. }
  72.  
  73. function add_new_context_sentences(target) {
  74. // Add '.context-sentence-group' to "Context Sentences" sections.
  75. Array.from(target.querySelectorAll('.subject-section__subtitle'))
  76. ?.find((node) => node.textContent.match('Context Sentences'))
  77. ?.closest('section')
  78. ?.querySelectorAll('.subject-section__text')
  79. ?.forEach((elem) => elem.classList.add('context-sentence-group'));
  80. }
  81.  
  82. }());