/* eslint-disable no-multi-spaces */ // ==UserScript== // @name Userscript App Core // @name:zh-CN 用户脚本应用核心 // @name:en Userscript App Core // @namespace Userscript-App // @version 0.2 // @description Userscript App Core For Userscript Web Apps // @description:zh-CN 用户脚本网页应用核心 // @description:en Userscript App Core For Userscript Web Apps // @author PY-DNG // @license GPL-v3 // @match http*://*/* // @connect * // @grant GM_info // @grant GM_addStyle // @grant GM_addElement // @grant GM_deleteValue // @grant GM_listValues // @grant GM_addValueChangeListener // @grant GM_removeValueChangeListener // @grant GM_setValue // @grant GM_getValue // @grant GM_log // @grant GM_getResourceText // @grant GM_getResourceURL // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_openInTab // @grant GM_xmlhttpRequest // @grant GM_download // @grant GM_getTab // @grant GM_saveTab // @grant GM_getTabs // @grant GM_notification // @grant GM_setClipboard // @grant GM_info // @grant unsafeWindow // @downloadURL none // ==/UserScript== (function __MAIN__() { 'use strict'; // function DoLog() {} // Arguments: level=LogLevel.Info, logContent, trace=false const [LogLevel, DoLog] = (function() { const LogLevel = { None: 0, Error: 1, Success: 2, Warning: 3, Info: 4, }; return [LogLevel, DoLog]; function DoLog() { // Get window const win = (typeof(unsafeWindow) === 'object' && unsafeWindow !== null) ? unsafeWindow : window; const LogLevelMap = {}; LogLevelMap[LogLevel.None] = { prefix: '', color: 'color:#ffffff' } LogLevelMap[LogLevel.Error] = { prefix: '[Error]', color: 'color:#ff0000' } LogLevelMap[LogLevel.Success] = { prefix: '[Success]', color: 'color:#00aa00' } LogLevelMap[LogLevel.Warning] = { prefix: '[Warning]', color: 'color:#ffa500' } LogLevelMap[LogLevel.Info] = { prefix: '[Info]', color: 'color:#888888' } LogLevelMap[LogLevel.Elements] = { prefix: '[Elements]', color: 'color:#000000' } // Current log level DoLog.logLevel = (win.isPY_DNG && win.userscriptDebugging) ? LogLevel.Info : LogLevel.Warning; // Info Warning Success Error // Log counter DoLog.logCount === undefined && (DoLog.logCount = 0); // Get args let [level, logContent, trace] = parseArgs([...arguments], [ [2], [1,2], [1,2,3] ], [LogLevel.Info, 'DoLog initialized.', false]); // Log when log level permits if (level <= DoLog.logLevel) { let msg = '%c' + LogLevelMap[level].prefix + (typeof GM_info === 'object' ? `[${GM_info.script.name}]` : '') + (LogLevelMap[level].prefix ? ' ' : ''); let subst = LogLevelMap[level].color; switch (typeof(logContent)) { case 'string': msg += '%s'; break; case 'number': msg += '%d'; break; default: msg += '%o'; break; } if (++DoLog.logCount > 512) { console.clear(); DoLog.logCount = 0; } console[trace ? 'trace' : 'log'](msg, subst, logContent); } } }) (); main(); function main() { unsafeWindow.GM_grant = GM_grant; unsafeWindow.dispatchEvent(new Event('gmready')); } function GM_grant(name) { const GMFuncs = { // Tampermonkey provides GM_addStyle: typeof GM_addStyle === 'function' ? GM_addStyle : null, GM_addElement: typeof GM_addElement === 'function' ? GM_addElement : null, GM_deleteValue: typeof GM_deleteValue === 'function' ? GM_deleteValue : null, GM_listValues: typeof GM_listValues === 'function' ? GM_listValues : null, GM_addValueChangeListener: typeof GM_addValueChangeListener === 'function' ? GM_addValueChangeListener : null, GM_removeValueChangeListener: typeof GM_removeValueChangeListener === 'function' ? GM_removeValueChangeListener : null, GM_setValue: typeof GM_setValue === 'function' ? GM_setValue : null, GM_getValue: typeof GM_getValue === 'function' ? GM_getValue : null, GM_log: typeof GM_log === 'function' ? GM_log : null, GM_getResourceText: typeof GM_getResourceText === 'function' ? GM_getResourceText : null, GM_getResourceURL: typeof GM_getResourceURL === 'function' ? GM_getResourceURL : null, GM_registerMenuCommand: typeof GM_registerMenuCommand === 'function' ? GM_registerMenuCommand : null, GM_unregisterMenuCommand: typeof GM_unregisterMenuCommand === 'function' ? GM_unregisterMenuCommand : null, GM_openInTab: typeof GM_openInTab === 'function' ? GM_openInTab : null, GM_xmlhttpRequest: typeof GM_xmlhttpRequest === 'function' ? GM_xmlhttpRequest : null, GM_download: typeof GM_download === 'function' ? GM_download : null, GM_getTab: typeof GM_getTab === 'function' ? GM_getTab : null, GM_saveTab: typeof GM_saveTab === 'function' ? GM_saveTab : null, GM_getTabs: typeof GM_getTabs === 'function' ? GM_getTabs : null, GM_notification: typeof GM_notification === 'function' ? GM_notification : null, GM_setClipboard: typeof GM_setClipboard === 'function' ? GM_setClipboard : null }; if (Object.keys(GMFuncs).includes(name)) { return GMFuncs[name]; } else { return null; } } function parseArgs(args, rules, defaultValues=[]) { // args and rules should be array, but not just iterable (string is also iterable) if (!Array.isArray(args) || !Array.isArray(rules)) { throw new TypeError('parseArgs: args and rules should be array') } // fill rules[0] (!Array.isArray(rules[0]) || rules[0].length === 1) && rules.splice(0, 0, []); // max arguments length const count = rules.length - 1; // args.length must <= count if (args.length > count) { throw new TypeError(`parseArgs: args has more elements(${args.length}) longer than ruless'(${count})`); } // rules[i].length should be === i if rules[i] is an array, otherwise it should be a function for (let i = 1; i <= count; i++) { const rule = rules[i]; if (Array.isArray(rule)) { if (rule.length !== i) { throw new TypeError(`parseArgs: rules[${i}](${rule}) should have ${i} numbers, but given ${rules[i].length}`); } if (!rule.every((num) => (typeof num === 'number' && num <= count))) { throw new TypeError(`parseArgs: rules[${i}](${rule}) should contain numbers smaller than count(${count}) only`); } } else if (typeof rule !== 'function') { throw new TypeError(`parseArgs: rules[${i}](${rule}) should be an array or a function.`) } } // Parse const rule = rules[args.length]; let parsed; if (Array.isArray(rule)) { parsed = [...defaultValues]; for (let i = 0; i < rule.length; i++) { parsed[rule[i]-1] = args[i]; } } else { parsed = rule(args, defaultValues); } return parsed; } })();