Console Importer

通过控制台导入 JS / CSS 库

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

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

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

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

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Zateb bir user-style yöneticim var, yükleyeyim!)

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