您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Easily import JS and CSS resources from Chrome console.
// ==UserScript== // @author Lete114 // @version 0.1 // @license MIT License // @name Console Importer // @description Easily import JS and CSS resources from Chrome console. // @match *://*/* // @icon data:image/png;base64,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 // @namespace https://github.com/Lete114/my-tampermonkey-scripts // @grant unsafeWindow // ==/UserScript== ;(function () { 'use strict' // https://github.com/pd4d10/console-importer const window = unsafeWindow const tiza = new Tiza() const PREFIX_TEXT = '[$i]: ' const prefix = tiza.color('blue').text const strong = tiza.color('blue').bold().text const error = tiza.color('red').text const log = (...args) => tiza.log(prefix(PREFIX_TEXT), ...args) const logError = (...args) => tiza.log(error(PREFIX_TEXT), ...args) /** * @type { Set<string> | null } */ let lastGlobalVariableSet = null /** * * @param { string } name * @returns */ function createBeforeLoad(name) { return () => { lastGlobalVariableSet = new Set(Object.keys(window)) log(strong(name), ' is loading, please be patient...') } } /** * * @param { string } name * @param { string? } url * @returns */ function createOnLoad(name, url) { return () => { const urlText = url ? `(${url})` : '' log(strong(name), `${urlText} is loaded.`) const currentGlobalVariables = Object.keys(window) const newGlobalVariables = currentGlobalVariables.filter( (key) => !lastGlobalVariableSet?.has(key) ) if (newGlobalVariables.length > 0) { log( 'The new global variables are as follows: ', strong(newGlobalVariables.join(',')), ' . Maybe you can use them.' ) } else { // maybe css request or script loaded already } // Update global variable list lastGlobalVariableSet = new Set(currentGlobalVariables) } } /** * * @param { string } name * @param { string? } url * @returns */ function createOnError(name, url) { return () => { const urlText = url ? `(${strong(url)})` : '' logError( 'Fail to load ', strong(name), ', is this URL', urlText, ' correct?' ) } } // Try to remove referrer for security // https://imququ.com/post/referrer-policy.html // https://www.w3.org/TR/referrer-policy/ function addNoReferrerMeta() { const originMeta = document.querySelector < HTMLMetaElement > 'meta[name=referrer]' if (originMeta) { // If there is already a referrer policy meta tag, save origin content // and then change it, call `remove` to restore it const content = originMeta.content originMeta.content = 'no-referrer' return function remove() { originMeta.content = content } } else { // Else, create a new one, call `remove` to delete it const meta = document.createElement('meta') meta.name = 'referrer' meta.content = 'no-referrer' document.head.appendChild(meta) return function remove() { // Removing meta tag directly not work, should set it to default first meta.content = 'no-referrer-when-downgrade' document.head.removeChild(meta) } } } /** * Insert script tag * @param { sting } url * @param { function } onload * @param { function } onerror */ function injectScript(url, onload, onerror) { const remove = addNoReferrerMeta() const script = document.createElement('script') script.src = url script.onload = onload script.onerror = onerror document.body.appendChild(script) remove() document.body.removeChild(script) } /** * Insert link tag * @param { string } url * @param { function } onload * @param { function } onerror */ function injectStyle(url, onload, onerror) { const remove = addNoReferrerMeta() const link = document.createElement('link') link.href = url link.rel = 'stylesheet' // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#Stylesheet_load_events link.onload = onload link.onerror = onerror document.head.appendChild(link) remove() // Should not remove <link> tag, unlike <script> } /** * * @param { string } url * @param {*} beforeLoad * @param {*} onload * @param {*} onerror * @returns */ function inject( url, beforeLoad = createBeforeLoad(url), onload = createOnLoad(url), onerror = createOnError(url) ) { beforeLoad() // Handle CSS if (/\.css$/.test(url)) { return injectStyle(url, onload, onerror) } // Handle JS return injectScript(url, onload, onerror) } /** * From cdnjs * https://cdnjs.com/ * @param { string } name */ function cdnjs(name) { log('Searching for ', strong(name), ', please be patient...') fetch(`https://api.cdnjs.com/libraries?search=${name}`, { referrerPolicy: 'no-referrer' }) .then((res) => res.json()) .then(({ results }) => { if (results.length === 0) { logError( 'Sorry, ', strong(name), ' not found, please try another keyword.' ) return } const matchedResult = results.filter((item) => item.name === name) const { name: exactName, latest: url } = matchedResult[0] || results[0] if (name !== exactName) { log( strong(name), ' not found, import ', strong(exactName), ' instead.' ) } inject( url, createBeforeLoad(exactName), createOnLoad(exactName, url), createOnError(exactName, url) ) }) .catch(() => { logError( 'There appears to be some trouble with your network. If you think this is a bug, please report an issue:' ) logError('https://github.com/pd4d10/console-importer/issues') }) } /** * From unpkg * https://unpkg.com * @param { string } name */ function unpkg(name) { createBeforeLoad(name)() const url = `https://unpkg.com/${name}` injectScript(url, createOnLoad(name, url), createOnError(name, url)) } /** * https://www.jsdelivr.com/esm * @param { string } name * @returns */ async function esm(name) { log(strong(name), '(esm) is loading, please be patient...') const res = await import(`https://esm.run/${name}`) return res } /** * Entry * @param { string } originName * @returns */ function importer(originName) { if (typeof originName !== 'string') { throw new Error('Argument should be a string, please check it.') } // Trim string const name = originName.trim() // If it is a valid URL, inject it directly if (/^https?:\/\//.test(name)) { return inject(name) } // If version specified, try unpkg if (name.indexOf('@') !== -1) { return unpkg(name) } return cdnjs(name) } importer.cdnjs = cdnjs importer.unpkg = unpkg importer.esm = esm // Do not output annoying ugly string of function content importer.toString = () => '$i' // Assign to console console.$i = importer // Do not break existing $i const win = window if (typeof win.$i === 'undefined') { win.$i = importer } else { log('$i is already in use, please use `console.$i` instead') } function Tiza(currentStyles, texts, styles) { if (currentStyles === void 0) { currentStyles = [] } if (texts === void 0) { texts = [] } if (styles === void 0) { styles = [] } var _this = this // Get method this.getCurrentStyles = function () { return _this._currentStyles } this.getTexts = function () { return _this._texts } this.getStyles = function () { return _this._styles } // Push a style to current Styles this.style = function (s) { return new Tiza( _this._currentStyles.concat([s]), _this._texts, _this._styles ) } // Alias for style method this.color = function (c) { return _this.style('color:' + c) } this.bgColor = function (c) { return _this.style('background-color:' + c) } this.bold = function () { return _this.style('font-weight:bold') } this.italic = function () { return _this.style('font-style:italic') } this.size = function (n) { var s = typeof n === 'number' ? n + 'px' : n // Convert number to px return _this.style('font-size:' + s) } // Clear all current styles this.reset = function () { return new Tiza([], _this._texts, _this._styles) } this.text = function () { var args = [] for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i] } var texts = _this._texts.slice() var styles = _this._styles.slice() args.forEach(function (arg) { if (arg instanceof Tiza) { texts.push.apply(texts, arg.getTexts()) styles.push.apply(styles, arg.getStyles()) } else { texts.push(arg) styles.push(_this._currentStyles.join(';')) } }) return new Tiza(_this._currentStyles, texts, styles) } this.space = function (count) { if (count === void 0) { count = 1 } return _this.text(repeat(' ', count)) } this.newline = function (count) { if (count === void 0) { count = 1 } return _this.text(repeat('\n', count)) } this._output = function (type) { return function () { var args = [] for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i] } var ins = _this.text.apply(_this, args) console[type].apply( console, [ ins .getTexts() .map(function (t) { return '%c' + t }) .join('') ].concat(ins._styles) ) return new Tiza(ins.getCurrentStyles()) } } this.log = this._output('log') this.info = this._output('info') this.warn = this._output('warn') this.error = this._output('error') this._currentStyles = currentStyles this._texts = texts this._styles = styles } })()