您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
简易的 Tampermonkey 脚本配置库
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/470224/1317473/Tampermonkey%20Config.js
// ==UserScript== // @name Tampermonkey Config // @name:zh-CN Tampermonkey 配置 // @license gpl-3.0 // @namespace http://tampermonkey.net/ // @version 0.7.0 // @description Simple Tampermonkey script config library // @description:zh-CN 简易的 Tampermonkey 脚本配置库 // @author PRO // @match * // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // ==/UserScript== // const debug = console.debug.bind(console, "[Tampermonkey Config]"); // Debug function const debug = () => { }; const GM_config_event = "GM_config_event"; // Compatibility with old versions function _GM_config_get(config_desc, prop) { return GM_getValue(prop, config_desc[prop].value); } const _GM_config_builtin_processors = { same: (v) => v, not: (v) => !v, int: (s) => { const value = parseInt(s); if (isNaN(value)) throw `Invalid value: ${s}, expected integer!`; return value; }, int_range: (s, min_s, max_s) => { const value = parseInt(s); if (isNaN(value)) throw `Invalid value: ${s}, expected integer!`; const min = (min_s === "") ? -Infinity : parseInt(min_s); const max = (max_s === "") ? +Infinity : parseInt(max_s); if (min !== NaN && value < min) throw `Invalid value: ${s}, expected integer >= ${min}!`; if (max !== NaN && value > max) throw `Invalid value: ${s}, expected integer <= ${max}!`; return value; }, float: (s) => { const value = parseFloat(s); if (isNaN(value)) throw `Invalid value: ${s}, expected float!`; return value; }, float_range: (s, min_s, max_s) => { const value = parseFloat(s); if (isNaN(value)) throw `Invalid value: ${s}, expected float!`; const min = (min_s === "") ? -Infinity : parseFloat(min_s); const max = (max_s === "") ? +Infinity : parseFloat(max_s); if (min !== NaN && value < min) throw `Invalid value: ${s}, expected float >= ${min}!`; if (max !== NaN && value > max) throw `Invalid value: ${s}, expected float <= ${max}!`; return value; }, }; const _GM_config_builtin_formatters = { normal: (name, value) => `${name}: ${value}`, boolean: (name, value) => `${name}: ${value ? "✔" : "✘"}`, }; const _GM_config_wrapper = { get: function (desc, prop) { // Return stored value, else default value const value = _GM_config_get(desc, prop); // Dispatch get event const event = new CustomEvent(GM_config_event, { detail: { type: "get", prop: prop, before: value, after: value } }); window.top.dispatchEvent(event); return value; }, set: function (desc, prop, value) { // Dispatch set event const before = _GM_config_get(desc, prop); const event = new CustomEvent(GM_config_event, { detail: { type: "set", prop: prop, before: before, after: value } }); // Store value const default_value = desc[prop].value; if (value === default_value && typeof GM_deleteValue === "function") { GM_deleteValue(prop); // Delete stored value if it's the same as default value debug(`🗑️ "${prop}" deleted`); } else { GM_setValue(prop, value); } window.top.dispatchEvent(event); return true; } }; const _GM_config_registered = {}; // prop => id // (Re-)register a single menu item, return its id function _GM_config_register_item(desc, config, inputs, prop) { const name = desc[prop].name; const orig = _GM_config_get(desc, prop); const input = desc[prop].input; const input_func = typeof input === "function" ? input : inputs[input]; const formatter = desc[prop].formatter; const formatter_func = typeof formatter === "function" ? formatter : _GM_config_builtin_formatters[formatter]; const option = { accessKey: desc[prop].accessKey, autoClose: desc[prop].autoClose, title: desc[prop].title, id: _GM_config_registered[prop], }; const id = GM_registerMenuCommand(formatter_func(name, orig), function () { let value; try { value = input_func(prop, orig); const processor = desc[prop].processor; if (typeof processor === "function") { // Process user input value = processor(value); } else if (typeof processor === "string") { const parts = processor.split("-"); const processor_func = _GM_config_builtin_processors[parts[0]]; if (processor_func !== undefined) // Process user input value = processor_func(value, ...parts.slice(1)); else // Unknown processor throw `Unknown processor: ${processor}`; } else { throw `Unknown processor format: ${typeof processor}`; } } catch (error) { alert("⚠️ " + error); return; } if (value !== orig) { config[prop] = value; } }, option); debug(`+ Registered menu command: prop="${prop}", id=${id}, option=`, option); return id; } // (Re-)register menu items function _GM_config_register(desc, config, inputs) { // Unregister old menu items for (const prop in _GM_config_registered) { const id = _GM_config_registered[prop]; GM_unregisterMenuCommand(id); delete _GM_config_registered[prop]; debug(`- Unregistered menu command: prop="${prop}", id=${id}`); } for (const prop in desc) { _GM_config_registered[prop] = _GM_config_register_item(desc, config, inputs, prop); } }; function GM_config(desc, menu = true) { // Register menu items based on given config description // Calc true default value const $default = Object.assign({ input: "prompt", processor: "same", formatter: "normal" }, desc["$default"] || {}); delete desc.$default; // Complete desc for (const key in desc) { desc[key] = Object.assign(Object.assign({}, $default), desc[key]); } // Get proxied config const config = new Proxy(desc, _GM_config_wrapper); // Built-in inputs const _GM_config_builtin_inputs = { current: (prop, orig) => orig, prompt: (prop, orig) => { const s = prompt(`🤔 New value for ${desc[prop].name}:`, orig); return s === null ? orig : s; }, }; // Register menu items if (window === window.top) { if (menu) { _GM_config_register(desc, config, _GM_config_builtin_inputs); } else { // Register menu items after user clicks "Show configuration" const id = GM_registerMenuCommand("Show configuration", function () { _GM_config_register(desc, config, _GM_config_builtin_inputs); }, { autoClose: false, title: "Show configuration options for this script" }); debug(`+ Registered menu command: prop="Show configuration", id=${id}`); _GM_config_registered[null] = id; } window.top.addEventListener(GM_config_event, (e) => { // Auto update menu items if (e.detail.type === "set" && e.detail.before !== e.detail.after) { debug(`🔧 "${e.detail.prop}" changed from ${e.detail.before} to ${e.detail.after}`); _GM_config_register_item(desc, config, _GM_config_builtin_inputs, e.detail.prop); } else if (e.detail.type === "get") { debug(`🔍 "${e.detail.prop}" requested, value is ${e.detail.after}`); } }); } // Return proxied config return config; };
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址