您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a button to easily start/stop PR merge when using bors
- // ==UserScript==
- // @name Github Bors Merge
- // @namespace https://sanketmishra.me
- // @version 0.1
- // @description Adds a button to easily start/stop PR merge when using bors
- // @author Sanket Mishra
- // @match https://github.com/*
- // @match https://*.github.com/*
- // @icon https://github.githubassets.com/favicons/favicon-dark.png
- // @grant none
- // ==/UserScript==
- (function () {
- "use strict";
- const BORS_MERGE_COMMENT = "bors r+";
- const BORS_CANCEL_COMMENT = "bors r-";
- const BORS_BUTTON_ID = "bors-button-submit";
- const BORS_MERGE_BUTTON_LABEL = "Bors Merge";
- const BORS_CANCEL_BUTTON_LABEL = "Bors Cancel";
- const BORS_PENDING_PREFIX = "borspending";
- const INTERVAL_DURATION = 3 * 1000; // 3 sec
- const PULL_REQUEST_COMMENTS_PAGE_REGEX = /\/pull\/\d+$/;
- const BORS_BUTTON_TYPE = "submit"; // change to "button" for testing
- let intervalId = null;
- function isPrCommentsPage() {
- return PULL_REQUEST_COMMENTS_PAGE_REGEX.test(window.location.pathname);
- }
- function isPrOpen() {
- return document.getElementsByClassName("State--open").length > 0;
- }
- function isBorsRunning() {
- const mergeStatusItems = [
- ...document.getElementsByClassName("merge-status-item"),
- ];
- return mergeStatusItems.some((item) => {
- const textContent = item.innerText
- .replaceAll(/[\W\n]+/g, "")
- .trim()
- .toLowerCase();
- return textContent.startsWith(BORS_PENDING_PREFIX);
- });
- }
- function getExistingBorsButton() {
- return document.getElementById(BORS_BUTTON_ID);
- }
- function isBorsButtonPresent() {
- return getExistingBorsButton() !== null;
- }
- function getExistingBorsButtonText() {
- return getExistingBorsButton()?.innerText ?? "";
- }
- function getBorsBaseButton() {
- const borsButton = document.createElement("button");
- borsButton.className = "btn-primary btn mr-1";
- borsButton.setAttribute("type", BORS_BUTTON_TYPE);
- borsButton.setAttribute("id", BORS_BUTTON_ID);
- return borsButton;
- }
- function getBorsButtonLabel(isBorsAlreadyRunning) {
- return isBorsAlreadyRunning
- ? BORS_CANCEL_BUTTON_LABEL
- : BORS_MERGE_BUTTON_LABEL;
- }
- function getBorsButtonCommentText(isBorsAlreadyRunning) {
- return isBorsAlreadyRunning ? BORS_CANCEL_COMMENT : BORS_MERGE_COMMENT;
- }
- function addOrReplaceBorsButton(borsButton, borsButtonParent) {
- if (isBorsButtonPresent()) {
- borsButtonParent.replaceChild(
- borsButton,
- borsButtonParent.firstElementChild
- );
- } else {
- borsButtonParent.insertBefore(
- borsButton,
- borsButtonParent.firstElementChild
- );
- }
- }
- function handleBorsButton() {
- const commentTextArea = document.getElementById("new_comment_field");
- const commentBoxButtonsParent = document.getElementById(
- "partial-new-comment-form-actions"
- ).firstElementChild;
- const commentButton = [
- ...commentBoxButtonsParent.getElementsByTagName("button"),
- ].filter((btn) => btn.innerText.toLowerCase() === "comment")[0];
- if (!commentButton) {
- return;
- }
- const isBorsAlreadyRunning = isBorsRunning();
- const borsButton = getBorsBaseButton();
- borsButton.innerText = getBorsButtonLabel(isBorsAlreadyRunning);
- borsButton.addEventListener("click", () => {
- commentTextArea.value = getBorsButtonCommentText(isBorsAlreadyRunning);
- });
- addOrReplaceBorsButton(borsButton, commentBoxButtonsParent);
- }
- function shouldHandleBorsButton() {
- if (!isPrCommentsPage()) {
- return false;
- }
- if (!isPrOpen()) {
- return false;
- }
- if (!isBorsButtonPresent()) {
- return true;
- }
- const borsButtonActualText = getExistingBorsButtonText();
- const borsButtonExpectedText = isBorsRunning()
- ? BORS_CANCEL_BUTTON_LABEL
- : BORS_MERGE_BUTTON_LABEL;
- return borsButtonActualText !== borsButtonExpectedText;
- }
- function execute() {
- if (shouldHandleBorsButton()) {
- handleBorsButton();
- }
- }
- function runOnInterval() {
- if (intervalId !== null) {
- clearInterval(intervalId);
- intervalId = null;
- }
- // Run it immediately for the first time
- execute();
- // Setup an interval to check whether the bors button is in DOM
- // Add it to the DOM if not present. Do nothing if present.
- intervalId = setInterval(() => {
- execute();
- }, INTERVAL_DURATION);
- }
- // Main function starts here
- runOnInterval();
- })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址