您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Imports and exports your WKOF settings
"use strict"; // ==UserScript== // @name Wanikani: Settings Exporter & Importer // @namespace http://tampermonkey.net/ // @version 1.1.4 // @description Imports and exports your WKOF settings // @author Kumirei // @match https://www.wanikani.com/* // @match https://preview.wanikani.com/* // @grant none // @license MIT // ==/UserScript== var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; // These lines are necessary to make sure that TSC does not put any exports in the // compiled js, which causes the script to crash var module = {}; ; (function () { return __awaiter(void 0, void 0, void 0, function () { function init() { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { wkof.include('Menu,Settings,Jquery'); wkof.ready('Jquery,Menu,Settings').then(install_menu).then(install_css); return [2 /*return*/]; }); }); } // Makes sure that WKOF is installed function confirm_wkof() { return __awaiter(this, void 0, void 0, function () { var response; return __generator(this, function (_a) { if (!wkof) { response = confirm("".concat(script_name, " requires WaniKani Open Framework.\nClick \"OK\" to be forwarded to installation instructions.")); if (response) { window.location.href = 'https://community.wanikani.com/t/instructions-installing-wanikani-open-framework/28549'; } } return [2 /*return*/]; }); }); } // Installs the options button in the menu function install_menu() { var config = { name: script_id, submenu: 'Open', title: script_name, on_click: open_settings }; wkof.Menu.insert_script_link(config); } // Opens settings dialogue when button is pressed function open_settings() { porter.available_scripts = get_script_ids(); var config = { script_id: script_id, title: script_name, pre_open: settings_pre_open, content: { "export": { type: 'page', label: 'Export', content: { select_scripts_export: { type: 'list', "default": {}, multi: true, full_width: true, size: 10, label: 'Select Scripts', hover_tip: "Choose which scripts' settings to export", content: Object.fromEntries(porter.available_scripts.map(function (id) { return [id, prettify_script_id(id)]; })), on_change: export_settings }, settings_string: { type: 'html', html: "<div class=\"row full\">" + " <div class=\"left\"><label>Settings string</label></div>" + " <div class=\"right\">" + " <textarea disabled id=\"exported_script_settings\" placeholder=\"Your exported settings will appear here\"></textarea>" + " </div>" + "</div>" }, buttons: { type: 'html', html: "<div class=\"porter_buttons\">" + " <button type=\"button\" action=\"copy\" class=\"ui-button ui-corner-all ui-widget\" title=\"Copy the settings string to your clipboard\">COPY</button>" + " <button type=\"button\" action=\"save\" class=\"ui-button ui-corner-all ui-widget\" title=\"Save the settings to a file\">SAVE</button>" + "</div>" } } }, "import": { type: 'page', label: 'Import', content: { settings_string: { type: 'html', html: "<div class=\"row full\">" + " <div class=\"left\"><label>Settings string</label></div>" + " <div class=\"right\">" + " <textarea id=\"import_script_settings\" placeholder=\"Paste your exported settings here or load settings from a file below\"></textarea>" + " </div>" + "</div>" }, load_button: { type: 'html', html: "<div class=\"row full\">" + " <div class=\"left\"><label>(or) Load from file</label></div>" + " <div class=\"right\"><input type=\"file\" action=\"load\" id=\"import_file\"></div" + "</div>" }, import_error: { type: 'html', html: "<div class=\"row full\">" + " <div id=\"import_error\">There was an error reading the settings</div>" + "</div>" }, select_scripts_import: { type: 'list', "default": {}, multi: true, size: 10, full_width: true, label: 'Select Scripts', hover_tip: "Choose which scripts' settings to import", content: {} }, import_button: { type: 'html', html: "<div class=\"porter_buttons\"><span class=\"success hidden\">Success!</span><button type=\"button\" action=\"import\" class=\"ui-button ui-corner-all ui-widget\" title=\"WARNING: This will override any existing settings for the selected scripts\">IMPORT</button></div>" } } } } }; var settings_dialog = new wkof.Settings(config); settings_dialog.open(); } // Retrieves a list of the available script function get_script_ids() { return Object.keys(wkof.file_cache.dir) .filter(function (key) { return /^wkof.settings..+/.test(key); }) .map(function (name) { return name.replace('wkof.settings.', ''); }); } // Makes the script ids a bit more user friendly function prettify_script_id(id) { return id .split(/[._]/) .map(function (word) { return word[0].toUpperCase() + word.substring(1); }) .join(' '); } // Add functionality to buttons and pasting settings function settings_pre_open(dialog) { porter.dialog = dialog; dialog.on('click', 'button', handle_button_press); dialog.on('keyup', '#import_script_settings', handle_settings_paste); dialog.on('change', '#import_file', import_from_file); } // Handles the button actions function handle_button_press(e) { var action = e.currentTarget.attributes.action.value; switch (action) { case 'copy': navigator.clipboard.writeText(porter.exported_settings); break; case 'save': download(porter.exported_settings, "WKOF_settings_export_".concat(new Date().toDateString(), ".txt")); break; case 'import': var selected = porter.dialog.find('[name="select_scripts_import"] :selected'); var scripts_1 = []; // @ts-ignore selected.each(function (i, elem) { return scripts_1.push(elem.value); }); import_settings(scripts_1); break; } } // Reads the settings into WKOF function import_settings(scripts) { for (var _i = 0, scripts_2 = scripts; _i < scripts_2.length; _i++) { var script = scripts_2[_i]; wkof.file_cache.save("wkof.settings.".concat(script), porter.imported_settings[script]); } // Show success message porter.dialog.find('span.success').removeClass('hidden'); } // Lets the user select a file to read for import function import_from_file(e) { var file = e.currentTarget.files[0]; if (file.type !== 'text/plain') toggle_error_message(true); var reader = new FileReader(); reader.readAsText(file); reader.onload = function () { var _a; import_from_text((_a = reader.result) !== null && _a !== void 0 ? _a : ''); }; reader.onerror = function () { toggle_error_message(true); }; } // Parses the the imported settings string function handle_settings_paste(e) { import_from_text(e.currentTarget.value); } // Imports from text function import_from_text(text) { var settings; try { settings = JSON.parse(text); toggle_error_message(false); populate_import_selection(settings); porter.imported_settings = settings; } catch (error) { toggle_error_message(true); return populate_import_selection({}); } } // Shows or hides the error message function toggle_error_message(on) { porter.dialog.attr('import_error', String(on)); } // Populates the selection of which script settings to import function populate_import_selection(settings) { var elem = porter.dialog.find('[name="select_scripts_import"]'); var html = ''; for (var _i = 0, _a = Object.keys(settings); _i < _a.length; _i++) { var script = _a[_i]; html += "<option value=\"".concat(script, "\" selected>").concat(prettify_script_id(script), "</option>"); } elem.html(html); } // Exports the selected setting to a string and puts them in the textarea function export_settings(name, scripts) { return __awaiter(this, void 0, void 0, function () { var to_export, settings; return __generator(this, function (_a) { switch (_a.label) { case 0: to_export = Object.entries(scripts) .filter(function (_a) { var script = _a[0], selected = _a[1]; return selected; }) .map(function (_a) { var script = _a[0]; return script; }); return [4 /*yield*/, load_script_settings(to_export)]; case 1: settings = _a.sent(); porter.exported_settings = JSON.stringify(settings); $('#exported_script_settings').val(porter.exported_settings); return [2 /*return*/]; } }); }); } // Loads the settings of a list of scripts function load_script_settings(scripts) { return __awaiter(this, void 0, void 0, function () { var settings, _i, scripts_3, script, _a, _b; return __generator(this, function (_c) { switch (_c.label) { case 0: settings = {}; _i = 0, scripts_3 = scripts; _c.label = 1; case 1: if (!(_i < scripts_3.length)) return [3 /*break*/, 4]; script = scripts_3[_i]; _a = settings; _b = script; return [4 /*yield*/, wkof.Settings.load(script)]; case 2: _a[_b] = _c.sent(); _c.label = 3; case 3: _i++; return [3 /*break*/, 1]; case 4: return [2 /*return*/, settings]; } }); }); } // Starts a download for a file function download(text, name) { var c = document.createElement('a'); c.download = name; var file = new Blob([text], { type: 'text/plain' }); c.href = window.URL.createObjectURL(file); c.click(); } // Installs the css function install_css() { var css = "\n#wkof_ds #wkofs_settings_exporter .porter_buttons {\n display: flex;\n justify-content: right;\n gap: 0.4em;\n}\n\n#wkof_ds #wkofs_settings_exporter #import_error {\n line-height: 1em;\n margin-top: 0.4em;\n color: red;\n display: none;\n}\n\n\n#wkof_ds #wkofs_settings_exporter .success {\n line-height: 1.5em;\n color: green;\n}\n\n\n#wkof_ds #wkofs_settings_exporter textarea { \n min-height: 5em;\n max-width: 100%;\n}\n\n#wkof_ds #wkofs_settings_exporter .porter_buttons_top { margin-bottom: 0.4em; }\n#wkof_ds [aria-describedby=\"wkofs_settings_exporter\"] .ui-dialog-buttonpane { display: none; }\n#wkof_ds #wkofs_settings_exporter[import_error=\"true\"] #import_error { display: block; }\n#wkof_ds #wkofs_settings_exporter #import_file { padding-left: 0; }\n#wkof_ds #wkofs_settings_exporter select { overflow: auto; }\n"; $('head').append("<style id=\"import-export-css\">".concat(css, "</style>")); } var script_id, script_name, wkof, porter; return __generator(this, function (_a) { switch (_a.label) { case 0: script_id = 'settings_exporter'; script_name = 'Settings Exporter'; wkof = window.wkof; // Init confirm_wkof(); window.addEventListener('turbo:load', function () { setTimeout(init, 0); }); wkof.include('Jquery'); return [4 /*yield*/, wkof.ready('Jquery')]; case 1: _a.sent(); porter = { available_scripts: [], exported_settings: '{}', imported_settings: {}, dialog: $() }; return [2 /*return*/]; } }); }); })(); module.exports = null;