"Ship It" GIF button for Github Review

Adds a button to Github to add "Let's ship it!" GIFs when reviewing PRs

目前為 2023-08-19 提交的版本,檢視 最新版本

// ==UserScript==
// @name         "Ship It" GIF button for Github Review
// @namespace    happyvikingasasds
// @version      1.2.0
// @grant        none
// @license      MIT
// @description  Adds a button to Github to add "Let's ship it!" GIFs when reviewing PRs
// @author       HappyViking
// @grant        none
// @match        https://github.com/*
// ==/UserScript==

const delay = (t) => new Promise((r) => setTimeout(r, t))

const main = () => {
  attemptButtonSetup()

  const rootHtmlNode = document.documentElement
  const config = { childList: true };
  const callback = (mutationList, observer) => {
    if (mutationList.filter(x => x.addedNodes.length > 0).length > 0) {
      delay(1000).then(attemptButtonSetup)
    }
  };

  const observer = new MutationObserver(callback);
  observer.observe(rootHtmlNode, config);
}

const attemptGetPRReviewSection = () => {
  const feedbackModal = document.getElementById("review-changes-modal")
  if (!feedbackModal) return null;
  const buttonPanelQuery = feedbackModal.getElementsByClassName("form-actions")
  if (buttonPanelQuery.length == 0) return null;
  return buttonPanel = buttonPanelQuery[0]
}

const attemptGetNewCommentSection = () => {
  const commentFormSection = document.getElementById("partial-new-comment-form-actions")
  console.log(commentFormSection)
  if (!commentFormSection) return null;
  const sampleButton = commentFormSection.querySelector("button")
  console.log(sampleButton)
  if (!sampleButton) return null;
  return sampleButton.parentElement.parentElement
}

const attemptButtonSetup = () => {

  onClickTarget = ""
  buttonID = ""
  buttonParent = null

  if (!document.getElementById("shipitbuttonpr")) {
    buttonParent = attemptGetPRReviewSection()
    if (buttonParent) {
      onClickTarget = "#pull_request_review_body"
      buttonID = "shipitbuttonpr"
    }
  }

  if (!buttonParent && !document.getElementById("shipitbuttonissue")) {
    buttonParent = attemptGetNewCommentSection()
    if (buttonParent) {
      onClickTarget = "#new_comment_field"
      buttonID = "shipitbuttonissue"
    }
  }

  if (!buttonParent) return

  //Have to make it a div cuz some forms in Github have all buttons perform automatic logic, which I don't want
  const newButton = document.createElement("div")
  newButton.id = buttonID
  buttonParent.prepend(newButton)
  //Copying from the existing "submit" button
  //But if you want you can also look into more styles from:
  //https://github.githubassets.com/assets/primer-8f43f7721dc7.css
  //though I think the suffix to "primer" might change by the time you read this
  newButton.classList = "Button--primary Button--small Button float-left mr-1"
  const buttonContentHolder = document.createElement("span")
  buttonContentHolder.className = "Button-content"
  newButton.append(buttonContentHolder)
  const buttonLabel = document.createElement("span")
  buttonLabel.className = "Button-label"
  buttonContentHolder.append(buttonLabel)
  buttonLabel.innerHTML = "Ship that shit"

  const theme = window.getComputedStyle(newButton).getPropertyValue("color-scheme"); //Cant just access via "style" because it's passed down to the button; it's not inline
  if (theme == "light") {
    newButton.style.backgroundImage = "linear-gradient(319deg, rgba(255,126,1,1) 8%, rgba(229,110,21,1) 40%, rgba(179,52,4,1) 81%)"
  } else {
    newButton.style.backgroundImage = "linear-gradient(0deg, rgba(212,74,38,1) 0%, rgba(254,128,13,1) 100%)"
  }

  const template = document.createElement('template'); //<template /> is specifically meant for string->html logic
  //Taken fron https://tabler-icons.io/i/sailboat and slightly modified (no color information so github will take care of that)
  template.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
  <path d="M2 20a2.4 2.4 0 0 0 2 1a2.4 2.4 0 0 0 2 -1a2.4 2.4 0 0 1 2 -1a2.4 2.4 0 0 1 2 1a2.4 2.4 0 0 0 2 1a2.4 2.4 0 0 0 2 -1a2.4 2.4 0 0 1 2 -1a2.4 2.4 0 0 1 2 1a2.4 2.4 0 0 0 2 1a2.4 2.4 0 0 0 2 -1"></path>
  <path d="M4 18l-1 -3h18l-1 3"></path>
  <path d="M11 12h7l-7 -9v9"></path>
  <path d="M8 7l-2 5"></path>
  </svg>`

  const buttonIcon = template.content.firstChild;
  buttonIcon.className = "Button--visual"
  newButton.append(buttonIcon)

  newButton.addEventListener("click", () => {
    const textarea = document.querySelector(onClickTarget)
    textarea.value += `\n\n<img src="https://i.shipit.today" height=100/>\n<sup>Let's ship it! <a href="https://shipit.today/">Img source.<a/></sup>`
  })
}

main()

QingJ © 2025

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