您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
为生产构建的Vue2或Vue3应用强制开启Vue Devtools
当前为
// ==UserScript== // @name Force Enable Vue Devtools // @version 0.2.2 // @author Huang-Huang Bao <[email protected]> (https://github.com/EHfive) // @description Force enable Vue Devtools for any Vue2 or Vue3 production build. // @homepage https://github.com/EHfive/userscripts/tree/master/userscripts/enbale-vue-devtools // @supportURL https://github.com/EHfive/userscripts/issues // @namespace https://eh5.me // @name:zh-CN 强制开启Vue Devtools // @name:zh-TW 強制開啓Vue Devtools // @description:zh-CN 为生产构建的Vue2或Vue3应用强制开启Vue Devtools // @description:zh-TW 爲生產構建的Vue2或Vue3應用強制開啓Vue Devtools // @license MIT // @run-at document-start // @noframes // @include /^.*$/ // @grant unsafeWindow // @grant GM_info // @grant GM.info // ==/UserScript== /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = "https://localhost:9000/"; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 1); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports) { !function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);n(1);(function(){"object"==typeof unsafeWindow&&unsafeWindow&&(unsafeWindow.GM=this.GM)}).call(window)},function(e,t){(function(){"undefined"==typeof GM&&(this.GM={}),"undefined"==typeof GM_addStyle&&(this.GM_addStyle=e=>{"use strict";let t=document.getElementsByTagName("head")[0];if(t){let n=document.createElement("style");return n.setAttribute("type","text/css"),n.textContent=e,t.appendChild(n),n}return null}),"undefined"==typeof GM_registerMenuCommand&&(this.GM_registerMenuCommand=(e,t,n)=>{if(!document.body)return void("loading"===document.readyState&&document.documentElement&&"html"===document.documentElement.localName?new MutationObserver((o,r)=>{document.body&&(r.disconnect(),GM_registerMenuCommand(e,t,n))}).observe(document.documentElement,{childList:!0}):console.error("GM_registerMenuCommand got no body."));let o=document.body.getAttribute("contextmenu"),r=o?document.querySelector("menu#"+o):null;r||(r=document.createElement("menu"),r.setAttribute("id","gm-registered-menu"),r.setAttribute("type","context"),document.body.appendChild(r),document.body.setAttribute("contextmenu","gm-registered-menu"));let u=document.createElement("menuitem");u.textContent=e,u.addEventListener("click",t,!0),r.appendChild(u)}),"undefined"==typeof GM_getResourceText&&(this.GM_getResourceText=e=>{"use strict";return GM.getResourceUrl(e).then(e=>fetch(e)).then(e=>e.text()).catch((function(e){return GM.log("Request failed",e),null}))}),Object.entries({log:console.log.bind(console),info:GM_info}).forEach(([e,t])=>{t&&void 0===GM[e]&&(GM[e]=t)}),Object.entries({GM_addStyle:"addStyle",GM_deleteValue:"deleteValue",GM_getResourceURL:"getResourceUrl",GM_getValue:"getValue",GM_listValues:"listValues",GM_notification:"notification",GM_openInTab:"openInTab",GM_registerMenuCommand:"registerMenuCommand",GM_setClipboard:"setClipboard",GM_setValue:"setValue",GM_xmlhttpRequest:"xmlHttpRequest",GM_getResourceText:"getResourceText"}).forEach(([e,t])=>{let n=this[e];n&&void 0===GM[t]&&(GM[t]=function(...e){return new Promise((t,o)=>{try{t(n.apply(this,e))}catch(e){o(e)}})})})}).call(window)}]); /***/ }), /* 1 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; // ESM COMPAT FLAG __webpack_require__.r(__webpack_exports__); // EXTERNAL MODULE: /home/eh5/Projects/userscripts/packages/polyfills/dist/index.js var dist = __webpack_require__(0); // CONCATENATED MODULE: /home/eh5/Projects/userscripts/.yarn/cache/consola-npm-2.15.0-71e35f623c-9a20844425.zip/node_modules/consola/src/logLevels.js const LogLevel = {}; LogLevel[LogLevel.Fatal = 0] = 'Fatal'; LogLevel[LogLevel.Error = 0] = 'Error'; LogLevel[LogLevel.Warn = 1] = 'Warn'; LogLevel[LogLevel.Log = 2] = 'Log'; LogLevel[LogLevel.Info = 3] = 'Info'; LogLevel[LogLevel.Success = 3] = 'Success'; LogLevel[LogLevel.Debug = 4] = 'Debug'; LogLevel[LogLevel.Trace = 5] = 'Trace'; LogLevel[LogLevel.Silent = -Infinity] = 'Silent'; LogLevel[LogLevel.Verbose = Infinity] = 'Verbose'; // CONCATENATED MODULE: /home/eh5/Projects/userscripts/.yarn/cache/consola-npm-2.15.0-71e35f623c-9a20844425.zip/node_modules/consola/src/types.js /* harmony default export */ var src_types = ({ // Silent silent: { level: -1 }, // Level 0 fatal: { level: LogLevel.Fatal }, error: { level: LogLevel.Error }, // Level 1 warn: { level: LogLevel.Warn }, // Level 2 log: { level: LogLevel.Log }, // Level 3 info: { level: LogLevel.Info }, success: { level: LogLevel.Success }, // Level 4 debug: { level: LogLevel.Debug }, // Level 5 trace: { level: LogLevel.Trace }, // Verbose verbose: { level: LogLevel.Trace }, // Legacy ready: { level: LogLevel.Info }, start: { level: LogLevel.Info } }); // CONCATENATED MODULE: /home/eh5/Projects/userscripts/.yarn/cache/consola-npm-2.15.0-71e35f623c-9a20844425.zip/node_modules/consola/src/utils/index.js function isPlainObject(obj) { return Object.prototype.toString.call(obj) === '[object Object]'; } // TODO: remove for consola@3 function isLogObj(arg) { // Should be plain object if (!isPlainObject(arg)) { return false; } // Should contains either 'message' or 'args' field if (!arg.message && !arg.args) { return false; } // Handle non-standard error objects if (arg.stack) { return false; } return true; } // CONCATENATED MODULE: /home/eh5/Projects/userscripts/.yarn/cache/consola-npm-2.15.0-71e35f623c-9a20844425.zip/node_modules/consola/src/consola.js let paused = false; const queue = []; class consola_Consola { constructor(options = {}) { this._reporters = options.reporters || []; this._types = options.types || src_types; this.level = options.level !== undefined ? options.level : 3; this._defaults = options.defaults || {}; this._async = options.async !== undefined ? options.async : undefined; this._stdout = options.stdout; this._stderr = options.stderr; this._mockFn = options.mockFn; this._throttle = options.throttle || 1000; this._throttleMin = options.throttleMin || 5; // Create logger functions for current instance for (const type in this._types) { this[type] = this._wrapLogFn(Object.assign({ type }, this._types[type], this._defaults)); } // Use _mockFn if is set if (this._mockFn) { this.mockTypes(); } // Keep serialized version of last log this._lastLogSerialized = undefined; this._lastLog = undefined; this._lastLogTime = undefined; this._lastLogCount = 0; this._throttleTimeout = undefined; } get stdout() { return this._stdout || console._stdout; // eslint-disable-line no-console } get stderr() { return this._stderr || console._stderr; // eslint-disable-line no-console } create(options) { return new consola_Consola(Object.assign({ reporters: this._reporters, level: this.level, types: this._types, defaults: this._defaults, stdout: this._stdout, stderr: this._stderr, mockFn: this._mockFn }, options)); } withDefaults(defaults) { return this.create({ defaults: Object.assign({}, this._defaults, defaults) }); } withTag(tag) { return this.withDefaults({ tag: this._defaults.tag ? this._defaults.tag + ':' + tag : tag }); } addReporter(reporter) { this._reporters.push(reporter); return this; } removeReporter(reporter) { if (reporter) { const i = this._reporters.indexOf(reporter); if (i >= 0) { return this._reporters.splice(i, 1); } } else { this._reporters.splice(0); } return this; } setReporters(reporters) { this._reporters = Array.isArray(reporters) ? reporters : [reporters]; return this; } wrapAll() { this.wrapConsole(); this.wrapStd(); } restoreAll() { this.restoreConsole(); this.restoreStd(); } wrapConsole() { for (const type in this._types) { // Backup original value if (!console['__' + type]) { // eslint-disable-line no-console console['__' + type] = console[type]; // eslint-disable-line no-console } // Override console[type] = this[type]; // eslint-disable-line no-console } } restoreConsole() { for (const type in this._types) { // Restore if backup is available if (console['__' + type]) { // eslint-disable-line no-console console[type] = console['__' + type]; // eslint-disable-line no-console delete console['__' + type]; // eslint-disable-line no-console } } } wrapStd() { this._wrapStream(this.stdout, 'log'); this._wrapStream(this.stderr, 'log'); } _wrapStream(stream, type) { if (!stream) { return; } // Backup original value if (!stream.__write) { stream.__write = stream.write; } // Override stream.write = data => { this[type](String(data).trim()); }; } restoreStd() { this._restoreStream(this.stdout); this._restoreStream(this.stderr); } _restoreStream(stream) { if (!stream) { return; } if (stream.__write) { stream.write = stream.__write; delete stream.__write; } } pauseLogs() { paused = true; } resumeLogs() { paused = false; // Process queue const _queue = queue.splice(0); for (const item of _queue) { item[0]._logFn(item[1], item[2]); } } mockTypes(mockFn) { this._mockFn = mockFn || this._mockFn; if (typeof this._mockFn !== 'function') { return; } for (const type in this._types) { this[type] = this._mockFn(type, this._types[type]) || this[type]; } } _wrapLogFn(defaults) { function logFn() { if (paused) { queue.push([this, defaults, arguments]); return; } return this._logFn(defaults, arguments); } return logFn.bind(this); } _logFn(defaults, args) { if (defaults.level > this.level) { return this._async ? Promise.resolve(false) : false; } // Construct a new log object const logObj = Object.assign({ date: new Date(), args: [] }, defaults); // Consume arguments if (args.length === 1 && isLogObj(args[0])) { Object.assign(logObj, args[0]); } else { logObj.args = Array.from(args); } // Aliases if (logObj.message) { logObj.args.unshift(logObj.message); delete logObj.message; } if (logObj.additional) { if (!Array.isArray(logObj.additional)) { logObj.additional = logObj.additional.split('\n'); } logObj.args.push('\n' + logObj.additional.join('\n')); delete logObj.additional; } // Normalize type and tag to lowercase logObj.type = typeof logObj.type === 'string' ? logObj.type.toLowerCase() : ''; logObj.tag = typeof logObj.tag === 'string' ? logObj.tag.toLowerCase() : ''; // Resolve log /** * @param newLog false if the throttle expired and * we don't want to log a duplicate */ const resolveLog = (newLog = false) => { const repeated = this._lastLogCount - this._throttleMin; if (this._lastLog && repeated > 0) { const args = [...this._lastLog.args]; if (repeated > 1) { args.push(`(repeated ${repeated} times)`); } this._log({ ...this._lastLog, args }); this._lastLogCount = 1; } // Log if (newLog) { this._lastLog = logObj; if (this._async) { return this._logAsync(logObj); } else { this._log(logObj); } } }; // Throttle clearTimeout(this._throttleTimeout); const diffTime = this._lastLogTime ? logObj.date - this._lastLogTime : 0; this._lastLogTime = logObj.date; if (diffTime < this._throttle) { try { const serializedLog = JSON.stringify([logObj.type, logObj.tag, logObj.args]); const isSameLog = this._lastLogSerialized === serializedLog; this._lastLogSerialized = serializedLog; if (isSameLog) { this._lastLogCount++; if (this._lastLogCount > this._throttleMin) { // Auto-resolve when throttle is timed out this._throttleTimeout = setTimeout(resolveLog, this._throttle); return; // SPAM! } } } catch (_) {// Circular References } } resolveLog(true); } _log(logObj) { for (const reporter of this._reporters) { reporter.log(logObj, { async: false, stdout: this.stdout, stderr: this.stderr }); } } _logAsync(logObj) { return Promise.all(this._reporters.map(reporter => reporter.log(logObj, { async: true, stdout: this.stdout, stderr: this.stderr }))); } } // Legacy support consola_Consola.prototype.add = consola_Consola.prototype.addReporter; consola_Consola.prototype.remove = consola_Consola.prototype.removeReporter; consola_Consola.prototype.clear = consola_Consola.prototype.removeReporter; consola_Consola.prototype.withScope = consola_Consola.prototype.withTag; consola_Consola.prototype.mock = consola_Consola.prototype.mockTypes; consola_Consola.prototype.pause = consola_Consola.prototype.pauseLogs; consola_Consola.prototype.resume = consola_Consola.prototype.resumeLogs; // Export class /* harmony default export */ var consola = (consola_Consola); // CONCATENATED MODULE: /home/eh5/Projects/userscripts/.yarn/cache/consola-npm-2.15.0-71e35f623c-9a20844425.zip/node_modules/consola/src/reporters/browser.js class BrowserReporter { constructor(options) { this.options = Object.assign({}, options); this.defaultColor = '#7f8c8d'; // Gray this.levelColorMap = { 0: '#c0392b', // Red 1: '#f39c12', // Yellow 3: '#00BCD4' // Cyan }; this.typeColorMap = { success: '#2ecc71' // Green }; } log(logObj) { const consoleLogFn = logObj.level < 1 // eslint-disable-next-line no-console ? console.__error || console.error : // eslint-disable-next-line no-console logObj.level === 1 && console.warn ? console.__warn || console.warn : console.__log || console.log; // Type const type = logObj.type !== 'log' ? logObj.type : ''; // Tag const tag = logObj.tag ? logObj.tag : ''; // Styles const color = this.typeColorMap[logObj.type] || this.levelColorMap[logObj.level] || this.defaultColor; const style = ` background: ${color}; border-radius: 0.5em; color: white; font-weight: bold; padding: 2px 0.5em; `; const badge = `%c${[tag, type].filter(Boolean).join(':')}`; // Log to the console if (typeof logObj.args[0] === 'string') { consoleLogFn(`${badge}%c ${logObj.args[0]}`, style, // Empty string as style resets to default console style '', ...logObj.args.slice(1)); } else { consoleLogFn(badge, style, ...logObj.args); } } } // CONCATENATED MODULE: ./src/logger.js const pkgName = "enable-vue-devtools"; const logger = new consola({ reporters: [new BrowserReporter()], defaults: { tag: pkgName } }); /* harmony default export */ var src_logger = (logger); // CONCATENATED MODULE: ./src/main.js /* harmony default export */ var main = (main_main); const _global = typeof unsafeWindow === 'object' && unsafeWindow || globalThis; // devtool hook should be ready when <body> exists const _devtoolHook = _global.__VUE_DEVTOOLS_GLOBAL_HOOK__; function main_main() { if (!_devtoolHook) { src_logger.warn('No Vue Devtools hook found', _global.location); return; } observeVueRoot(function (app, disconnect) { emitDevtoolVue2Hooks(app); }, function (app, disconnect) { emitDevtoolVue3Hooks(app); }); } function emitDevtoolVue2Hooks(app) { let Vue = app.constructor; const store = app.$store; while (Vue.super) { // find base Vue Vue = Vue.super; } Vue.config.devtools = true; src_logger.info('enabling devtools for Vue instance', app); // must re-emit 'init' if this Vue is different with other Vue(s) // otherwise this `Vue`'s root instance would not be added to Devtools store // https://github.com/vuejs/vue-devtools/blob/933063fd06860464be4bfd8c83ba09d7fc2c753e/packages/app-backend/src/index.js#L218-L225 _devtoolHook.emit('init', Vue); // TODO validate Vuex instance if (store) { src_logger.info('enabling devtools for Vuex instance', store); devtoolStorePlugin(store, _devtoolHook); } } function emitDevtoolVue3Hooks(app) { if (!Array.isArray(_devtoolHook.apps)) return; if (_devtoolHook.apps.includes(app)) return; let version = app.version; if (!version) { src_logger.warn('no Vue version detected, fallback to "3.0.0"'); version = '3.0.0'; } src_logger.info('enabling devtools for Vue 3 instance', app); // FIXME: impossible to get those Symbols, // https://github.com/vuejs/vue-next/blob/410e7abbbb78e83989ad2e5a1793c290129dfdc7/packages/runtime-core/src/devtools.ts#L38 const types = { Fragment: undefined, Text: undefined, Comment: undefined, Static: undefined }; _devtoolHook.emit('app:init', app, version, types); const unmount = app.unmount.bind(app); app.unmount = function () { _devtoolHook.emit('app:unmount', app); unmount(); }; } function checkVue2Instance(target) { const vue = target && target.__vue__; return !!(vue && typeof vue === 'object' && vue._isVue && typeof vue.constructor === 'function'); } function checkVue3Instance(target) { const app = target && target.__vue_app__; return !!app; } function noop() {} function observeVueRoot(callbackVue2, callbackVue3) { if (typeof callbackVue2 !== 'function') { callbackVue2 = noop; } if (typeof callbackVue3 !== 'function') { callbackVue3 = noop; } const vue2RootSet = new WeakSet(); const vue3RootSet = new WeakSet(); const observer = new MutationObserver((mutations, observer) => { const disconnect = observer.disconnect.bind(observer); for (const { target } of mutations) { if (!target) { return; } else if (checkVue2Instance(target)) { const inst = target.__vue__; const root = inst.$parent ? inst.$root : inst; if (vue2RootSet.has(root)) { // already callback, continue loop continue; } vue2RootSet.add(root); callbackVue2(root, disconnect); } else if (checkVue3Instance(target)) { const app = target.__vue_app__; if (vue3RootSet.has(app)) { // already callback, continue loop continue; } vue3RootSet.add(app); callbackVue3(app, disconnect); } } }); observer.observe(document.documentElement, { attributes: true, subtree: true, childList: true }); return observer; } function devtoolStorePlugin(store, devtoolHook) { store._devtoolHook = devtoolHook; devtoolHook.emit('vuex:init', store); devtoolHook.on('vuex:travel-to-state', targetState => { store.replaceState(targetState); }); store.subscribe((mutation, state) => { devtoolHook.emit('vuex:mutation', mutation, state); }); } // CONCATENATED MODULE: ./src/index.js try { main(); if (false) {} } catch (e) { src_logger.error(e); } /***/ }) /******/ ]);