Add banner to github PRs for easier copying of the PR's head ref

What the title says

  1. // ==UserScript==
  2. // @name Add banner to github PRs for easier copying of the PR's head ref
  3. // @description What the title says
  4. // @namespace ahappyviking
  5. // @version 1
  6. // @match https://github.com/*
  7. // @require https://unpkg.com/bundled-github-url-detector@1.0.0/index.js
  8. // @license MIT
  9. // ==/UserScript==
  10.  
  11. const gh = githubUrlDetection
  12.  
  13. const ELEMENT_ID = "head-ref-banner"
  14.  
  15.  
  16. const main = () => {
  17. const preExistingElement = document.getElementById(ELEMENT_ID)
  18. if (preExistingElement){
  19. preExistingElement.remove()
  20. }
  21.  
  22. if (!gh.isPR() && !gh.isActionRun()) return
  23. const baseRefNameParent = document.querySelector(".commit-ref.css-truncate.user-select-contain.head-ref")
  24. const textContent = baseRefNameParent?.querySelector("span")
  25. let baseRefName = textContent?.textContent
  26. if (!baseRefName) baseRefName = "[UNKNOWN]"
  27.  
  28. const urlTokens = window.location.href.split("/")
  29.  
  30. let baseUrl = ""
  31. if (gh.isPR()){
  32. baseUrl = urlTokens.slice(0, urlTokens.indexOf("pull") + 2).join("/")
  33. }else{
  34. const searchParams = (new URL(window.location)).searchParams;
  35. let prNumber = searchParams.get("pr");
  36. if (!prNumber) return
  37. baseUrl = urlTokens.slice(0, urlTokens.indexOf("actions")).join("/") + `/pull/${prNumber}`
  38. }
  39. console.log(baseUrl)
  40.  
  41. const parent = document.createElement('div')
  42. parent.id = ELEMENT_ID
  43. parent.style.position = "fixed"
  44. parent.style.top = 0
  45. parent.style.left = "50%"
  46. parent.style.translate = "translateX(-50%)"
  47. parent.style.webkitTransform = "translateX(-50%)"
  48. parent.style.display = "flex"
  49. parent.style.flexDirection = "row"
  50.  
  51. const baseStyle = {
  52. width: "fit-content",
  53. height: "14px",
  54. fontSize: "10px",
  55. cursor: "pointer",
  56. fontWeight: "bold",
  57. textAlign: "center",
  58. color: "white",
  59. paddingLeft: "16px",
  60. paddingRight: "16px",
  61. }
  62.  
  63. const headRefEle = document.createElement("div")
  64. for (const [property, value] of Object.entries(baseStyle)) headRefEle.style[property] = value;
  65. headRefEle.style.background = "#3f5e18"
  66. headRefEle.textContent = baseRefName
  67. headRefEle.addEventListener("click", () => navigator.clipboard.writeText(baseRefName))
  68.  
  69. const convoEle = document.createElement("div")
  70. for (const [property, value] of Object.entries(baseStyle)) convoEle.style[property] = value;
  71. convoEle.style.background = "#5c286c"
  72. convoEle.textContent = "Conversation"
  73. const convoEleParent = document.createElement("a")
  74. convoEleParent.href = baseUrl
  75. convoEleParent.appendChild(convoEle)
  76.  
  77. const filesEle = document.createElement("div")
  78. for (const [property, value] of Object.entries(baseStyle)) filesEle.style[property] = value;
  79. filesEle.style.background = "#5c286c"
  80. filesEle.textContent = "Review"
  81. const filesEleParent = document.createElement("a")
  82. filesEleParent.href = baseUrl + "/files"
  83. filesEleParent.appendChild(filesEle)
  84.  
  85.  
  86. parent.appendChild(convoEleParent)
  87. parent.appendChild(headRefEle)
  88. parent.appendChild(filesEleParent)
  89. document.body.appendChild(parent)
  90. }
  91.  
  92. main()
  93. document.addEventListener("soft-nav:end", main);
  94. document.addEventListener("navigation:end", main);