Github anchor enhance

Enhance all github link with badges

Versão de: 09/11/2019. Veja: a última versão.

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

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este 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==
// @namespace https://github.com/NateScarlet/Scripts/tree/master/user-script
// @name     Github anchor enhance
// @description Enhance all github link with badges
// @version  17
// @grant    GM.xmlHttpRequest
// @run-at   document-end
// @include	 *
// ==/UserScript==
const reservedUsername = [
    "topics",
    "search",
    "ghost",
    "pulls",
    "issues",
    "marketplace",
    "explore",
    "discover",
    "notifications",
    "new",
    "organizations",
    "settings",
    "site",
    "about",
    "contact",
    "pricing",
    "apps",
    "features",
    "password_reset",
];
const allBadgeClasses = [
    "added-stars-badge",
    "added-last-commit-badge",
    "added-followers-badge",
];
class URLParseResult {
    constructor({ user, repo }) {
        this.user = user;
        this.repo = repo;
    }
    equals(other) {
        return other.repo === this.repo && other.user === this.user;
    }
}
URLParseResult.EMPTY = new URLParseResult({});
function parseURL(v) {
    const match = v.match(/^https?:\/\/github.com\/([^/]*?)(?:\/([^/]*?))?(?:\.git)?(?:[#?].*)?(?:$|\/)/);
    if (!match) {
        return URLParseResult.EMPTY;
    }
    if (reservedUsername.includes(match[1])) {
        return URLParseResult.EMPTY;
    }
    return new URLParseResult({
        user: match[1],
        repo: match[2],
    });
}
async function appendBadge(el, className, url) {
    if (el.classList.contains(className)) {
        return;
    }
    return new Promise((resolve, reject) => {
        GM.xmlHttpRequest({
            method: "GET",
            url: url,
            onload: resp => {
                if (resp.status === 200) {
                    if (!el.classList.contains(className)) {
                        const img = document.createElement("img");
                        img.src = `data:image/svg+xml;base64,${btoa(resp.response)}`;
                        const containerClassNames = [
                            "natescarlet-gmail-com",
                            "badge-container",
                        ];
                        const selector = containerClassNames.map(i => "." + i).join("");
                        /** @type {HTMLElement} */
                        const container = el.querySelector(selector) || document.createElement("span");
                        el.appendChild(container);
                        container.classList.add(...containerClassNames);
                        container.append(img);
                        img.style.order = allBadgeClasses.indexOf(className).toString();
                        container.style.display = "inline-flex";
                        el.classList.add(className);
                    }
                    resolve();
                }
                reject(`${resp.status}: ${url}`);
            },
            onerror: reject,
        });
    });
}
async function appendStarsBadge(el) {
    const { repo, user } = parseURL(el.href);
    if (!(user && repo)) {
        return;
    }
    await appendBadge(el, "added-stars-badge", `https://img.shields.io/github/stars/${user}/${repo}.svg?style=social`);
}
async function appendLastCommitBadge(el) {
    const { repo, user } = parseURL(el.href);
    if (!(user && repo)) {
        return;
    }
    await appendBadge(el, "added-last-commit-badge", `https://img.shields.io/github/last-commit/${user}/${repo}.svg`);
}
async function appendFollowersBadge(el) {
    const { user } = parseURL(el.href);
    if (!user) {
        return;
    }
    await appendBadge(el, "added-followers-badge", `https://img.shields.io/github/followers/${user}.svg?style=social`);
}
(async function () {
    document.addEventListener("mouseover", async (e) => {
        if (e.target instanceof HTMLAnchorElement) {
            const el = e.target;
            if (parseURL(location.href).equals(parseURL(el.href))) {
                // Skip self link
                return;
            }
            try {
                await Promise.all([
                    appendStarsBadge(el),
                    appendLastCommitBadge(el),
                    appendFollowersBadge(el),
                ]);
            }
            catch (err) {
                console.error(err);
            }
        }
    }, {});
})();