一键查看历年 GitHub 的贡献图

在 GitHub 中查看用户历年的贡献图。

目前為 2024-04-21 提交的版本,檢視 最新版本

// ==UserScript==
// @name         一键查看历年 GitHub 的贡献图
// @namespace    https://green-wall.leoku.dev
// @version      1.0.5
// @description  在 GitHub 中查看用户历年的贡献图。
// @author       LeoKu(https://leoku.dev)
// @match        https://github.com/*
// @run-at       document-end
// @icon         https://green-wall.leoku.dev/favicon.svg
// @grant        GM.xmlHttpRequest
// @homepageURL  https://github.com/Codennnn/Green-Wall
// @license      MIT
// ==/UserScript==

var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
var _a, _b, _c;
var isProfile = new RegExp(/^https:\/\/github\.com\/([^/]+)$/).test(window.location.href);
if (isProfile) {
    var ORIGIN_1 = 'https://green-wall.leoku.dev';
    var produceData_1 = function (_a) {
        var data = _a.data;
        var contributionCalendars = data.contributionCalendars.map(function (cur) {
            var rows = [[], [], [], [], [], [], []];
            cur.weeks.forEach(function (_a) {
                var days = _a.days;
                if (days.length !== 7) {
                    var newDays = __spreadArray([], days, true);
                    for (var i = 0; i <= 6; i++) {
                        var theDay = newDays.at(i);
                        var weekday = i;
                        if (theDay && typeof theDay.weekday === 'number') {
                            if (theDay.weekday === weekday) {
                                rows[theDay.weekday].push(theDay);
                            }
                            else {
                                newDays.splice(i, 0, { level: 'Null', weekday: weekday });
                                rows[i].push({ level: 'Null', weekday: weekday });
                            }
                        }
                        else {
                            rows[i].push({ level: 'Null', weekday: weekday });
                        }
                    }
                }
                else {
                    days.forEach(function (day) {
                        if (typeof day.weekday === 'number') {
                            rows[day.weekday].push(day);
                        }
                    });
                }
            });
            var calendar = {
                total: cur.total,
                year: cur.year,
                rows: rows,
            };
            return calendar;
        });
        return {
            contributionCalendars: contributionCalendars,
        };
    };
    var createGraph_1 = function (params) {
        var year = params.year, total = params.total, rows = params.rows;
        var table = document.createElement('table');
        table.classList.add('ContributionCalendar-grid');
        table.style.borderSpacing = '3px';
        table.style.overflow = 'hidden';
        table.style.position = 'relative';
        var tbody = document.createElement('tbody');
        var tr = document.createElement('tr');
        tr.style.height = '10px';
        rows.forEach(function (row) {
            var clonedTr = tr.cloneNode();
            var htmlStr = '';
            row.forEach(function (col, idx) {
                var td = '<td></td>';
                if (col.level !== "Null" /* ContributionLevel.Null */) {
                    var level = col.level === "NONE" /* ContributionLevel.NONE */
                        ? 0
                        : col.level === "FIRST_QUARTILE" /* ContributionLevel.FIRST_QUARTILE */
                            ? 1
                            : col.level === "SECOND_QUARTILE" /* ContributionLevel.SECOND_QUARTILE */
                                ? 2
                                : col.level === "THIRD_QUARTILE" /* ContributionLevel.THIRD_QUARTILE */
                                    ? 3
                                    : 4;
                    td = "\n        <td\n          tabindex=\"-1\"\n          data-ix=\"".concat(idx, "\"\n          style=\"width: 10px\"\n          data-level=\"").concat(level, "\"\n          role=\"gridcell\"\n          class=\"ContributionCalendar-day\"\n        ></td>\n        ");
                }
                htmlStr += td;
            });
            if (clonedTr instanceof HTMLTableRowElement) {
                clonedTr.innerHTML = htmlStr;
                tbody.append(clonedTr);
            }
        });
        table.appendChild(tbody);
        var graphItem = document.createElement('div');
        var countText = document.createElement('div');
        countText.style.marginBottom = '5px';
        countText.textContent = "".concat(total, " contributions in ").concat(year);
        graphItem.append(countText, table);
        return { graphItem: graphItem };
    };
    var createDialog = function (params) {
        var username = params.username;
        var dialog = document.createElement('dialog');
        dialog.id = 'green-wall-dialog';
        dialog.classList.add('Overlay', 'Overlay-whenNarrow', 'Overlay--size-medium-portrait', 'Overlay--motion-scaleFadeOverlay', 'Overlay-whenNarrow', 'Overlay--size-medium-portrait', 'Overlay--motion-scaleFade');
        dialog.style.minWidth = '720px';
        dialog.style.maxHeight = 'calc(100vh - 50px)';
        var handleDialogClose = function () {
            dialog.close();
            document.body.classList.remove('has-modal');
        };
        dialog.addEventListener('click', function () {
            handleDialogClose();
        });
        // ---
        var wrap = document.createElement('div');
        wrap.style.display = 'flex';
        wrap.style.flexDirection = 'column';
        wrap.style.overflow = 'hidden';
        wrap.addEventListener('click', function (ev) {
            ev.stopPropagation();
        });
        // ---
        var dialogHeader = document.createElement('div');
        dialogHeader.classList.add('Overlay-header');
        var contentWrap = document.createElement('div');
        contentWrap.classList.add('Overlay-headerContentWrap');
        var titleWrap = document.createElement('div');
        titleWrap.classList.add('Overlay-titleWrap');
        var title = document.createElement('h1');
        title.classList.add('Overlay-title');
        title.textContent = "".concat(username, "'s GreenWall");
        var actionWrap = document.createElement('div');
        actionWrap.classList.add('Overlay-actionWrap');
        var actionButton = document.createElement('button');
        actionButton.classList.add('close-button', 'Overlay-closeButton');
        actionButton.setAttribute('type', 'button');
        actionButton.innerHTML = "\n  <svg aria-hidden=\"true\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-x\">\n    <path d=\"M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z\"></path>\n  </svg>\n  ";
        actionButton.addEventListener('click', function (ev) {
            ev.stopPropagation();
            handleDialogClose();
        });
        // ---
        var dialogBody = document.createElement('div');
        dialogBody.classList.add('Overlay-body');
        dialogBody.style.overflowY = 'auto';
        var dialogContent = document.createElement('div');
        dialogContent.style.display = 'flex';
        dialogContent.style.flexDirection = 'column';
        dialogContent.style.rowGap = '10px';
        dialogContent.style.alignItems = 'center';
        dialogContent.style.padding = 'var(--stack-padding-normal, 1rem)';
        // ---
        var dialogFooter = document.createElement('div');
        dialogFooter.classList.add('Overlay-footer', 'Overlay-footer--alignEnd', 'Overlay-footer--divided');
        var openExtrnalBtn = document.createElement('button');
        var btnContent = document.createElement('span');
        btnContent.classList.add('Button-label');
        btnContent.textContent = 'Open in Green Wall';
        openExtrnalBtn.classList.add('Button', 'Button--primary', 'Button--medium');
        openExtrnalBtn.addEventListener('click', function () {
            window.open("".concat(ORIGIN_1, "/user/").concat(username), '_blank');
        });
        titleWrap.append(title);
        actionWrap.append(actionButton);
        contentWrap.append(titleWrap, actionWrap);
        openExtrnalBtn.append(btnContent);
        dialogHeader.append(contentWrap);
        dialogBody.append(dialogContent);
        dialogFooter.append(openExtrnalBtn);
        wrap.append(dialogHeader, dialogBody, dialogFooter);
        dialog.append(wrap);
        document.body.append(dialog);
        return { dialog: dialog, dialogContent: dialogContent };
    };
    var profileArea = document.querySelector('.Layout-sidebar .h-card .js-profile-editable-replace');
    var refNode = (_b = (_a = document.querySelector('.js-profile-editable-replace > .d-flex.flex-column')) === null || _a === void 0 ? void 0 : _a.nextSibling) === null || _b === void 0 ? void 0 : _b.nextSibling;
    if (profileArea instanceof HTMLElement && refNode instanceof HTMLElement) {
        var username_1 = (_c = document
            .querySelector('meta[property="profile:username"]')) === null || _c === void 0 ? void 0 : _c.getAttribute('content');
        if (username_1) {
            var block = document.createElement('div');
            block.classList.add('border-top', 'color-border-muted', 'pt-3', 'mt-3', 'clearfix', 'hide-sm', 'hide-md');
            var title = document.createElement('h2');
            title.classList.add('h4', 'mb-2');
            title.textContent = 'Green Wall';
            var openBtn = document.createElement('button');
            openBtn.classList.add('btn');
            openBtn.textContent = ' ⬜ 🟩 View All Green';
            block.appendChild(title);
            block.appendChild(openBtn);
            profileArea.insertBefore(block, refNode);
            var _d = createDialog({ username: username_1 }), dialog_1 = _d.dialog, dialogContent_1 = _d.dialogContent;
            var hasLoaded_1 = false;
            var handleLoadError_1 = function () {
                dialogContent_1.innerHTML = '';
                var errorBlock = document.createElement('div');
                errorBlock.style.display = 'flex';
                errorBlock.style.flexDirection = 'column';
                errorBlock.style.alignItems = 'center';
                var tip = document.createElement('p');
                tip.textContent = 'The process of obtaining data has an exception.';
                var retryBtn = document.createElement('button');
                retryBtn.classList.add('btn');
                retryBtn.textContent = 'Retry';
                retryBtn.addEventListener('click', function () {
                    // eslint-disable-next-line @typescript-eslint/no-use-before-define
                    handleLoadData_1();
                });
                errorBlock.append(tip, retryBtn);
                dialogContent_1.append(errorBlock);
            };
            var handleLoadData_1 = function () {
                var loading = "\n        <svg aria-label=\"Loading\" style=\"box-sizing: content-box; color: var(--color-icon-primary);\" width=\"32\" height=\"32\" viewBox=\"0 0 16 16\" fill=\"none\" data-view-component=\"true\" class=\"anim-rotate\">\n          <circle cx=\"8\" cy=\"8\" r=\"7\" stroke=\"currentColor\" stroke-opacity=\"0.25\" stroke-width=\"2\" vector-effect=\"non-scaling-stroke\" fill=\"none\"></circle>\n          <path d=\"M15 8a7.002 7.002 0 00-7-7\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" vector-effect=\"non-scaling-stroke\"></path>\n        </svg>\n        ";
                dialogContent_1.innerHTML = loading;
                GM.xmlHttpRequest({
                    method: 'GET',
                    url: "".concat(ORIGIN_1, "/api/contribution/").concat(username_1),
                    onload: function (response) {
                        try {
                            dialogContent_1.innerHTML = '';
                            var data = JSON.parse(response.responseText);
                            var xData = produceData_1(data);
                            xData.contributionCalendars.forEach(function (calendar) {
                                var graphItem = createGraph_1(calendar).graphItem;
                                dialogContent_1.append(graphItem);
                            });
                            hasLoaded_1 = true;
                        }
                        catch (_a) {
                            handleLoadError_1();
                        }
                    },
                    onerror: function (err) {
                        console.error('[Green Wall]: ', err);
                        handleLoadError_1();
                    },
                });
            };
            var handleDialogOpen_1 = function () {
                dialog_1.showModal();
                document.body.classList.add('has-modal');
                if (!hasLoaded_1) {
                    handleLoadData_1();
                }
            };
            openBtn.addEventListener('click', function () {
                handleDialogOpen_1();
            });
        }
    }
    else {
        console.warn('[Green Wall]: Target node not found.');
    }
}


QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址