您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Highlight items in the lesson picker by JLPT level using WKOF
// ==UserScript== // @name WK Lesson Picker JLPT Highlighter // @namespace http://tampermonkey.net/ // @version 0.1 // @description Highlight items in the lesson picker by JLPT level using WKOF // @author Benjie Genchel // @match https://www.wanikani.com/subject-lessons/picker // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant none // @run-at document-end // @license MIT // ==/UserScript== (async function () { console.log("Is this working at all"); 'use strict'; let script_name = 'Lesson Picker JLPT Highlighter'; if (!window.wkof) { if (confirm(script_name+' requires Wanikani Open Framework.\nDo you want to be forwarded to the installation instructions?')) { window.location.href = 'https://community.wanikani.com/t/instructions-installing-wanikani-open-framework/28549'; } return; } console.log('made it here') let wkof = window.wkof; async function loadJLPT() { const urls = { N1: "https://raw.githubusercontent.com/stephenmk/yomitan-jlpt-vocab/main/yomitan-jlpt-vocab/term_meta_bank_1.json", N2: "https://raw.githubusercontent.com/stephenmk/yomitan-jlpt-vocab/main/yomitan-jlpt-vocab/term_meta_bank_2.json", N3: "https://raw.githubusercontent.com/stephenmk/yomitan-jlpt-vocab/main/yomitan-jlpt-vocab/term_meta_bank_3.json", N4: "https://raw.githubusercontent.com/stephenmk/yomitan-jlpt-vocab/main/yomitan-jlpt-vocab/term_meta_bank_4.json", N5: "https://raw.githubusercontent.com/stephenmk/yomitan-jlpt-vocab/main/yomitan-jlpt-vocab/term_meta_bank_5.json" } const rawJLPT = {}; for (const [level, url] of Object.entries(urls)) { const text = await wkof.load_file(url); rawJLPT[level] = JSON.parse(text); } return rawJLPT; } const rawJLPT = await loadJLPT(); const jLPTMap = {}; for (const [level, entries] of Object.entries(rawJLPT)) { for (const [term, , meta] of entries) { if (!term || !meta || !meta.frequency || !meta.frequency.displayValue) continue; if (!(term in jLPTMap)) { jLPTMap[term] = level; } } } const JLPT_COLORS = { N1: '#e81717', // red N2: '#f28705', // orange N3: '#fcec08', // yellow N4: '#1f9eff', // blue N5: '#05f205', // green null: '#e8ebe8' // neutral gray }; function injectLegend() { // 1. Create the legend container const legend = document.createElement('div'); legend.style.display = 'flex'; legend.style.flexDirection = 'column'; legend.style.position = 'fixed'; legend.style.right = '10px' legend.style.zIndex = '10'; legend.style.gap = '20px'; legend.style.padding = '12px'; legend.style.marginBottom = '12px'; legend.style.borderRadius = '6px'; legend.style.background = '#fafafa'; legend.style.fontSize = '16px'; legend.style.boxShadow = '1px 1px 10px rgba(0, 0, 0, 0.5)'; // 2. Build each color‐label pair const entries = [ { level: 'N1', color: JLPT_COLORS.N1 }, { level: 'N2', color: JLPT_COLORS.N2 }, { level: 'N3', color: JLPT_COLORS.N3 }, { level: 'N4', color: JLPT_COLORS.N4 }, { level: 'N5', color: JLPT_COLORS.N5 }, { level: 'None', color: JLPT_COLORS.null }, ]; const legendHeader = document.createElement('div'); legendHeader.style.display = 'flex'; legendHeader.style.alignItems = 'center'; legendHeader.style.gap = '10px'; const legendHeaderTitle = document.createElement('span'); legendHeaderTitle.textContent = 'JLPT Legend'; legendHeader.appendChild(legendHeaderTitle); legend.appendChild(legendHeader); entries.forEach(({ level, color }) => { const item = document.createElement('div'); item.style.display = 'flex'; item.style.alignItems = 'center'; item.style.gap = '10px'; const swatch = document.createElement('span'); swatch.style.display = 'inline-block'; swatch.style.width = '16px'; swatch.style.height = '16px'; swatch.style.background = color; swatch.style.borderRadius = '4px'; item.appendChild(swatch); const label = document.createElement('span'); label.textContent = level; item.appendChild(label); legend.appendChild(item); }); const pickerSection = document.querySelector('.lesson-picker'); pickerSection.parentNode.insertBefore(legend, pickerSection); } wkof.include('ItemData'); wkof.ready('ItemData').then(start); function start() { injectLegend(); const tiles = document.querySelectorAll('.lesson-picker__subject'); tiles.forEach(tile => { const term = tile.querySelector('span > div > span'); const slug = term ? term.textContent.trim() : null; const wrapper = document.createElement('div'); wrapper.style.outline = `4px solid ${JLPT_COLORS[jLPTMap[slug]]}` wrapper.style.borderRadius = window.getComputedStyle(term).borderRadius; const parent = tile.parentNode; parent.replaceChild(wrapper, tile); wrapper.appendChild(tile); }); }; })();