您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a wkof filter for visually similar kanji
// ==UserScript== // @name Wanikani Open Framework: Visually similar kanji filter // @namespace http://tampermonkey.net/ // @version 2.0.0 // @description Adds a wkof filter for visually similar kanji // @author Kumirei // @include https://www.wanikani.com/* // @include *preview.wanikani.com* // @grant none // ==/UserScript== /*jshint esversion: 8 */ (function(wkof) { let script_id = "VSKFilter"; if (!wkof) return; var visuallySimilarFilename = 'https://raw.githubusercontent.com/mwil/wanikani-userscripts/master/wanikani-similar-kanji/db/stroke_edit_dist_esc.json'; var visuallySimilarData; async function get_data() { let data = await wkof.load_file(visuallySimilarFilename, true); visuallySimilarData = JSON.parse(data); } function ageCache(){ // periodically ages the cache let oneMonth = 1000*60*60*24*30; var now = Date.now(); if (wkof.settings[script_id] === undefined) wkof.settings[script_id] = {}; if (wkof.settings[script_id].lastTime === undefined){ wkof.settings[script_id].lastTime = now; wkof.Settings.save(script_id); } let lastTime = wkof.settings[script_id].lastTime; if (now > lastTime + oneMonth){ wkof.file_cache.delete(visuallySimilarFilename); wkof.settings[script_id].lastTime = now; wkof.Settings.save(script_id); } } // Turns comma separated lists into arrays. Supports latin and Japanese commas. Converts Japanese periods into latin decimal points // Adapted from a handy function of rfindley function split_list(str) {return str.replace(/./g,'.').replace(/[、,]/g,',').replace(/[\s ]+/g,' ').trim().replace(/ *, */g, ',').toLowerCase().split(',').filter(function(name) {return (name.length > 0);});} // Translate Japanese numerals into latin so they can be parsed into numbers by Number() function tr(text) { return text.replace( /[0123456789]/g, (chr => '0123456789'.charAt('0123456789'.indexOf( chr )))); } // Create an array of visually similar kanji for all search terms function makeVisuallySimilarArrays(str){ var arr = split_list(str); if (arr.length === 0) return []; // compute the similarity threshold if one is provided var threshold = 0.0; // default if threshold is absent var first = Number(tr(arr[0])); if (!isNaN(first)){ // number is present - calculate threshold if (arr.length <= 1) return []; var second = Number(tr(arr[1])); if (isNaN(second)) { // decimal separator not a comma - first is threshold threshold = first; arr = arr.splice(1); } else { // decimal separator is a comma - calculate threshold threshold = first + second/10; arr = arr.splice(2); } } return arr.reduce(filterThreshold, []); function filterThreshold(running, kanji){ if (visuallySimilarData[kanji] === undefined) return running; // ignore trash input for (var data of visuallySimilarData[kanji]){ if (data.score >= threshold) running.push(data.kan); } return running; } } // Adds the filter to wkof function register_filter(data) { wkof.ready('ItemData.registry').then(()=>{ wkof.ItemData.registry.sources.wk_items.filters.include_visually_similar_kanji = { filter_func: function(filter_value, item){if (item.object === "kanji") item.visually_similar_kanji = visuallySimilarData[item.data.characters]; return true;} }; wkof.ItemData.registry.sources.wk_items.filters.visually_similar_kanji = { type: 'text', label: 'LY Visually Similar', placeholder: '0.5,人、能、力', hover_tip: 'Select the kanji whose similar kanji you want to study.\nMultiple search terms are separated by commas.\n\n'+ 'You may specify a similarity threshold as as a real number\nbetween 0 and 1 at the beginning of the search terms.\n'+ '0 means all similar kanji. Higher numbers give fewer kanji.\n\nThis filter uses similarity data by Lars Yencken.', default: '', filter_func: function (filterValue, item){return (item.object === 'kanji' && filterValue.indexOf(item.data.characters) >= 0);}, filter_value_map: makeVisuallySimilarArrays, }; wkof.set_state(script_id, 'ready'); }); } // startup get_data(); register_filter(); wkof.include('Settings'); wkof.ready('Settings') .then(function(){return wkof.Settings.load(script_id);}) .then(ageCache); })(window.wkof);