您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
GitHub 仓库的 /commits 页面,每个 commit 的头像前面 增加时间 YYYY-MM-DD HH:MM
当前为
// ==UserScript== // @name GitHub Commits Time Formatter // @namespace http://tampermonkey.net/ // @version 2025-03-19 // @description GitHub 仓库的 /commits 页面,每个 commit 的头像前面 增加时间 YYYY-MM-DD HH:MM // @author You // @match https://github.com/*/commits/* // @icon https://www.google.com/s2/favicons?sz=64&domain=github.com // @grant none // ==/UserScript== (function() { 'use strict'; // 从 title 属性中提取并格式化时间的函数 function formatDateTimeFromTitle(title) { const parts = title.match(/(\w+ \d+, \d{4}), (\d+:\d+ [AP]M)/); if (!parts) { return ""; } const [, datePart, timePart] = parts; const fullDateStr = `${datePart} ${timePart}`; const date = new Date(fullDateStr); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); return `${year}-${month}-${day} ${hours}:${minutes}`; } // 处理时间元素的函数 function processTimeElements() { const relativeTimeElements = document.querySelectorAll('relative-time[class^="sc-aXZVg"][class*="pl-1"]'); relativeTimeElements.forEach((timeElement) => { const title = timeElement.getAttribute('title'); if (title) { const formattedTime = formatDateTimeFromTitle(title); const targetDiv = timeElement.closest('li').querySelector('div[data-testid="author-avatar"]'); if (targetDiv) { // 检查是否已经存在格式化后的时间元素 const existingTimeSpan = targetDiv.previousElementSibling; if (existingTimeSpan && existingTimeSpan.tagName === 'SPAN' && existingTimeSpan.textContent === formattedTime) { return; // 如果已经存在则跳过 } // 创建新的 <span> 元素来显示格式化后的时间 const timeSpan = document.createElement('span'); timeSpan.textContent = formattedTime; timeSpan.style.whiteSpace = 'pre'; // 确保空格显示正常 timeSpan.style.marginRight = '10px'; // 添加右边距 // 在指定的 div 元素前面插入新的 <span> 元素 targetDiv.parentNode.insertBefore(timeSpan, targetDiv); } } }); } // 节流函数 function throttle(func, delay) { let timer = null; return function() { if (!timer) { func.apply(this, arguments); timer = setTimeout(() => { timer = null; }, delay); } }; } // 初始化 MutationObserver function initMutationObserver() { const throttledProcessTimeElements = throttle(processTimeElements, 500); // 每 500 毫秒最多执行一次 const observer = new MutationObserver((mutationsList) => { for (const mutation of mutationsList) { if (mutation.type === 'childList') { throttledProcessTimeElements(); } } }); const targetNode = document.body; const config = { childList: true, subtree: true }; observer.observe(targetNode, config); } // 主函数 function main() { processTimeElements(); initMutationObserver(); } main(); })();