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