Console Importer

通过控制台导入 JS / CSS 库

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

You will need to install an extension such as Tampermonkey to install this script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==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;
})();