GitHub Commits Quick Jump

Add "Jump to Start" and "Jump to End" buttons on GitHub commits page

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         GitHub Commits Quick Jump
// @namespace    https://github.com/aojunhao123
// @version      1.0.0
// @description  Add "Jump to Start" and "Jump to End" buttons on GitHub commits page
// @author       aojunhao123
// @license      MIT
// @match        https://github.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=github.com
// @homepageURL  https://github.com/aojunhao123/github-commits-quick-jump
// @supportURL   https://github.com/aojunhao123/github-commits-quick-jump/issues
// @grant        none
// @copyright    2026, aojunhao123(https://aojunhao.com)
// ==/UserScript==

(function() {
    'use strict';

    // 按钮容器 ID,用于防止重复插入
    const CONTAINER_ID = 'quick-jump-buttons';

    /**
     * 判断当前是否在 commits 页面
     */
    function isCommitsPage() {
        return /\/commits\//.test(window.location.pathname);
    }

    /**
     * 从仓库主页解析 commit 数量并存入 sessionStorage
     */
    function getCommits() {
        const elements = document.querySelectorAll("span .fgColor-default");
        for (const el of elements) {
            const match = el.innerText.match(/([\d,]+)\s*Commits?/i);
            if (match) {
                sessionStorage.setItem("commits", match[1]);
                return;
            }
        }
    }

    /**
     * 在 commits 页面插入跳转按钮
     */
    function insertButtons() {
        // 防止重复插入
        if (document.getElementById(CONTAINER_ID)) {
            return;
        }

        // 获取存储的 commit 数量
        const commitsStr = sessionStorage.getItem("commits");
        if (!commitsStr) {
            console.log('[Quick Jump] No commit count found, please visit repo main page first');
            return;
        }

        // 找到分页按钮
        const paginationNext = document.querySelector('a[data-testid="pagination-next-button"]');
        if (!paginationNext) {
            return;
        }

        const btnGroup = paginationNext.parentNode.parentNode;
        const commitsNum = parseInt(commitsStr.replace(/,/g, ""), 10);
        const basePath = window.location.pathname;

        // 创建按钮容器
        const container = document.createElement('div');
        container.id = CONTAINER_ID;
        container.style.cssText = 'display: flex; gap: 8px; margin-left: 16px;';

        // 创建 "Jump to Start" 按钮(回到最新的 commits,即第一页)
        const btnToStart = document.createElement('a');
        btnToStart.className = paginationNext.className;
        btnToStart.href = basePath;
        btnToStart.innerText = "⏮ First";
        btnToStart.title = "Jump to latest commits";

        // 创建 "Jump to End" 按钮(跳到最早的 commits,即最后一页)
        // 复用分页按钮的 href(包含 commit hash),只替换 offset 数字
        const btnToEnd = document.createElement('a');
        btnToEnd.className = paginationNext.className;
        btnToEnd.href = paginationNext.href.replace(/\+\d+/, `+${commitsNum - 35}`);
        btnToEnd.innerText = "Last ⏭";
        btnToEnd.title = "Jump to first commit";

        // 添加按钮到容器
        container.appendChild(btnToStart);
        container.appendChild(btnToEnd);

        // 插入到按钮组后面
        btnGroup.parentNode.insertBefore(container, btnGroup.nextSibling);
    }

    /**
     * 页面变化时的处理函数
     */
    function handlePageChange() {
        if (isCommitsPage()) {
            // 在 commits 页面,插入跳转按钮
            insertButtons();
        } else {
            // 在其他页面(如主页),尝试获取 commit 数量
            getCommits();
        }
    }

    // 监听 GitHub 的 Turbo 导航事件(SPA 页面切换)
    document.addEventListener('turbo:load', handlePageChange);

    // 首次加载时执行
    handlePageChange();
})();