Console Importer

通过控制台导入 JS / CSS 库

// ==UserScript==
// @name		Console Importer
// @name:en		Console Importer
// @description		通过控制台导入 JS / CSS 库
// @description:en		Import JavaScript or CSS Library in browser developer tool.
// @author		Yiero
// @version		1.2.0
// @match		https://*/*
// @license		GPL
// @icon		https://bbs.tampermonkey.net.cn/favicon.ico
// @run-at		document-body
// @grant		GM_addElement
// @grant		GM_xmlhttpRequest
// @namespace		https://github.com/AliubYiero/TamperMonkeyScripts/
// @connect		cdnjs.cloudflare.com
// @connect		cdn.bootcdn.net
// @connect		api.bootcdn.cn
// @connect		cdn.jsdelivr.net
// ==/UserScript==
var __defProp = Object.defineProperty;

var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
    enumerable: true,
    configurable: true,
    writable: true,
    value: value
}) : obj[key] = value;

var __publicField = (obj, key, value) => {
    __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
    return value;
};

class Info {
    constructor(projectName) {
        __publicField(this, "projectName");
        __publicField(this, "header");
        this.projectName = projectName;
        this.header = `[${projectName}]`;
    }
    log(...msg) {
        (() => {})(...this.contentInfo(...msg));
    }
    info(...msg) {
        console.info(...this.contentInfo(...msg));
    }
    warn(...msg) {
        console.warn(...this.contentInfo(...msg));
    }
    error(...msg) {
        console.error(...this.contentInfo(...msg));
    }
    group() {
        console.group(this.header);
    }
    groupEnd() {
        console.groupEnd();
    }
    contentInfo(...msg) {
        return [ this.header, ...msg ];
    }
}

function isCSS(url) {
    return url.endsWith("css");
}

const urlList = new Map;

function GMHttpRequest(url, method = "GET", paramOrData, GMXmlHttpRequestConfig = {}) {
    if (paramOrData && method === "GET") {
        const params = [];
        for (const key in paramOrData) {
            if (Object.hasOwnProperty.call(paramOrData, key)) {
                const value = paramOrData[key];
                params.push(`${key}=${JSON.stringify(value)}`);
            }
        }
        url += `?${params.join("?")}`;
    } else if (paramOrData && method === "POST") {
        GMXmlHttpRequestConfig.data = {
            ...paramOrData
        };
    }
    return new Promise(((resolve, reject) => {
        const newGMXmlHttpRequestConfig = {
            timeout: 2e4,
            ...GMXmlHttpRequestConfig,
            url: url,
            method: method,
            onload(response) {
                resolve(response);
            },
            onerror(error) {
                reject(error);
            }
        };
        GM_xmlhttpRequest(newGMXmlHttpRequestConfig);
    }));
}

const api_Bootcdn = async searchLibrary => {
    const bootcdnApiDetailDomain = "https://api.bootcdn.cn/libraries/";
    const bootcdnApiDomain = "https://cdn.bootcdn.net/ajax/libs/";
    const res = await GMHttpRequest(bootcdnApiDetailDomain + searchLibrary);
    let link = "";
    if (res.status !== 200) {
        return Promise.reject("Can not find library from bootcdn...");
    } else {
        const response = JSON.parse(res.response);
        const {filename: filename, version: version} = response[0];
        link = `${bootcdnApiDomain}/${searchLibrary}/${version}/${filename}`;
        print.log("\u4ece bootcdn \u4e2d\u67e5\u627e\u5230\u5e93: ", link);
        return Promise.resolve(link);
    }
};

async function getBootcdnLibrary(searchLibrary) {
    const reSearchLibrary = searchLibrary.endsWith(".js") ? searchLibrary.replace(".js", "") : searchLibrary + ".js";
    const searchLibraryList = [ searchLibrary, reSearchLibrary, searchLibrary.toLowerCase(), reSearchLibrary.toLowerCase() ];
    for (let i = 0; i < searchLibraryList.length; i++) {
        const searchLibrary2 = searchLibraryList[i];
        print.warn("\u6b63\u5728\u5c1d\u8bd5\u4ece bootcdn \u4e2d\u83b7\u53d6\u5e93: ", searchLibrary2);
        let link = "";
        try {
            link = await api_Bootcdn(searchLibrary2);
        } catch (e) {
            print.error("\u83b7\u53d6\u5e93\u5931\u8d25: ", searchLibrary2);
        }
        if (link.startsWith("http")) {
            return link;
        }
    }
    print.error("\u65e0\u6cd5\u4ece bootcdn \u4e2d\u83b7\u53d6\u5230\u5e93: ", searchLibrary);
    throw new Error(`Can not found library from bootcdn: ${searchLibrary}`);
}

async function getUrl(urlOrLibrary) {
    let url;
    if (urlOrLibrary.startsWith("https")) {
        url = urlOrLibrary;
    } else {
        url = await getBootcdnLibrary(urlOrLibrary);
    }
    return url;
}

async function installLibrary(urlOrLibrary) {
    print.group();
    const url = await getUrl(urlOrLibrary);
    if (urlList.has(url)) {
        print.error(`\u83b7\u53d6\u6570\u636e\u5931\u8d25...\n\u5f53\u524d\u9875\u9762\u4e2d\u5df2\u5b58\u5728\u5e93 [${url}]`);
        print.groupEnd();
        return;
    }
    print.info("\u6b63\u5728\u52a0\u8f7d\u6570\u636e...");
    GMHttpRequest(url).then((res => {
        if (res.status === 404) {
            print.error(`\u83b7\u53d6\u6570\u636e\u5931\u8d25...\nError: page not found, request an error url: ${url}`);
            print.groupEnd();
            return;
        } else if (res.status !== 200) {
            print.error(`\u83b7\u53d6\u6570\u636e\u5931\u8d25...\nError: ${res.responseText}`);
            print.groupEnd();
            return;
        }
        const scriptText = res.responseText;
        const isScript = !isCSS(url);
        const displayObj = {
            tag: isScript ? "script" : "style",
            content: isScript ? "\u811a\u672c" : "\u6837\u5f0f\u8868"
        };
        print.info(`\u6210\u529f\u83b7\u53d6${displayObj.content}, \u6b63\u5728\u8f7d\u5165\u9875\u9762...`);
        const element = GM_addElement(document.head, displayObj.tag, {
            textContent: scriptText
        });
        urlList.set(url, element);
        print.info(`${displayObj.content}\u8f7d\u5165\u6210\u529f.\n${url}`);
        print.groupEnd();
    }), (error => {
        print.error("\u83b7\u53d6\u6570\u636e\u5931\u8d25...\nError: ", error.error);
        print.groupEnd();
    }));
}

async function uninstallLibrary(url) {
    print.group();
    const element = urlList.get(await getUrl(url));
    if (!element) {
        print.warn("\u5f53\u524d\u9875\u9762\u672a\u5b89\u88c5\u5e93: \n", url);
        print.groupEnd();
        return;
    }
    element == null ? void 0 : element.remove();
    print.info(`\u5f53\u524d\u5e93\u5df2\u5220\u9664: \n`, url);
    urlList.delete(url);
    print.groupEnd();
}

const print = new Info("Console Importer");

(() => {
    unsafeWindow.$i = installLibrary;
    unsafeWindow.$o = getBootcdnLibrary;
    unsafeWindow.$ui = uninstallLibrary;
})();