[Userscript] Wanikani JLPT Items (for Self-Study Quiz)
Here’s the sample script I mentioned.
I modified the script a little so it now fetches the item data from an external file only when needed, so it’s pretty light-weight when not in use.
The external item data file needs to be on a server that grants CORS access to wanikani (or "*"
).
I’ve set up a sample with about 20 items on [https://www.wkstats.com/cors/wanikani/jlpt_items_v0.0.1.js]
Here’s the script source:
Source code
// ==UserScript==
// @name Wanikani JLPT Items (for Self-Study Quiz)
// @namespace rfindley
// @description Source for JLPT items in Self-Study Quiz
// @version 1.0.0
// @include https://www.wanikani.com/*
// @copyright 2018+, Robin Findley
// @license MIT; http://opensource.org/licenses/MIT
// @run-at document-end
// @grant none
// ==/UserScript==
window.jlpt_items = {};
(function(gobj) {
/* global $, wkof */
/* eslint no-multi-spaces: "off" */
var jlpt_items_file = 'https://www.wkstats.com/cors/wanikani/jlpt_items_v0.0.1.js';
//===================================================================
// Initialization of the Wanikani Open Framework.
//-------------------------------------------------------------------
var script_name = 'JLPT Items (for Self-Study Quiz)';
var wkof_version_needed = '1.0.45';
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;
}
if (wkof.version.compare_to(wkof_version_needed) === 'older') {
if (confirm(script_name+' requires Wanikani Open Framework version '+wkof_version_needed+'.\nDo you want to be forwarded to the update page?')) {
window.location.href = 'https://greasyfork.org/en/scripts/38582-wanikani-open-framework';
}
return;
}
wkof.include('ItemData');
wkof.ready('ItemData').then(startup);
//===================================================================
function jlpt_fetcher() {
if (gobj.jlpt_items !== undefined) return Promise.resolve(gobj.jlpt_items);
return wkof.load_script(jlpt_items_file, true /* use_cache */)
.then(parse_items);
}
//===================================================================
function parse_items() {
var jlpt_items = {};
var jlpt_level, items, item, idx;
var id_cnt = 0;
//------------------
for (jlpt_level in gobj.kanji) {
items = gobj.kanji[jlpt_level];
for (idx in items) {
item = items[idx];
jlpt_items['jlpt_' + id_cnt++] = {
object: 'kanji',
data: {
jlpt_level: jlpt_level,
characters: item[0],
meanings: to_meanings(item[1]),
readings: to_yomi(item[2], item[3])
}
};
}
}
//------------------
for (jlpt_level in gobj.vocabulary) {
items = gobj.vocabulary[jlpt_level];
for (idx in items) {
item = items[idx];
jlpt_items['jlpt_' + id_cnt++] = {
object: 'vocabulary',
data: {
jlpt_level: jlpt_level,
characters: item[0],
meanings: to_meanings(item[1]),
readings: to_readings(item[2], item[3])
}
};
}
}
//-------------------------------------------------------------------
function to_meanings(text) {
return split_list(text).map(function(meaning){return {meaning:meaning, primary:true, accepted_answer:true};});
}
//-------------------------------------------------------------------
function to_yomi(kunyomi, onyomi) {
return split_list(kunyomi).map(function(reading){return {type:'kunyomi', reading:reading, primary:true, accepted_answer:true};}).concat(
split_list(onyomi).map(function(reading){return {type:'onyomi', reading:reading, primary:true, accepted_answer:true};})
);
}
//-------------------------------------------------------------------
function to_readings(text) {
return split_list(text).map(function(reading){return {reading:reading, primary:true, accepted_answer:true};});
}
//-------------------------------------------------------------------
return jlpt_items;
}
//-------------------------------------------------------------------
function split_list(str) {return str.replace(/^\s+|\s*(,)\s*|\s+$/g, '$1').split(',').filter(function(name) {return (name.length > 0);});}
//===================================================================
var item_type_filter = {
type: 'multi',
label: 'Item type',
default: [],
content: {kanji:'Kanji',vocabulary:'Vocabulary'},
filter_func: function(filter_value, item){return filter_value[item.object] === true;},
hover_tip: 'Filter by item type (kanji, vocabulary)'
};
//===================================================================
var jlpt_level_filter = {
type: 'multi',
label: 'JLPT Level',
default: [],
content: {N5:'N5',N4:'N4',N3:'N3',N2:'N2',N1:'N1'},
filter_func: function(filter_value, item){return filter_value[item.data.jlpt_level] === true;},
hover_tip: 'Filter by JLPT Level (N5, N4, N3, N2, N1)'
};
//===================================================================
function startup() {
wkof.ItemData.registry.sources.jlpt_items = {
description:"JLPT",
fetcher:jlpt_fetcher,
filters:{
item_type:item_type_filter,
jlpt_level:jlpt_level_filter,
},
options:{}
};
}
})(window.jlpt_items);
(ping: @seanblue)