跳转到 Github Releases 页面

在 GitHub 仓库页面添加快速跳转到 Releases 页面的按钮

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name                    Go to Github Releases Page
// @name:zh-CN              跳转到 Github Releases 页面
// @namespace               https://github.com/xlsama/tampermonkey-scripts
// @version                 0.1.0
// @author                  xlsama
// @description             Add a quick link button to navigate to GitHub repository releases page
// @description:zh-CN       在 GitHub 仓库页面添加快速跳转到 Releases 页面的按钮
// @homepageURL             https://github.com/xlsama/tampermonkey-scripts
// @supportURL              https://github.com/xlsama/tampermonkey-scripts/issues
// @match                   *://github.com/*
// @include                 *://*github*
// @grant                   none
// @license                 MIT
// ==/UserScript==

// 判断当前path是否是一个 github repo,且位于项目的主页面
function isGithubRepo(path) {
  path = path.slice(0, -1)
  return path.split('/').length === 3
}

// 创建 package 图标 SVG 的辅助函数
function createPackageIcon() {
  const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
  svg.setAttribute('aria-hidden', 'true')
  svg.setAttribute('focusable', 'false')
  svg.setAttribute('class', 'octicon octicon-package')
  svg.setAttribute('viewBox', '0 0 16 16')
  svg.setAttribute('width', '16')
  svg.setAttribute('height', '16')
  svg.setAttribute('fill', 'currentColor')
  svg.setAttribute('display', 'inline-block')
  svg.setAttribute('overflow', 'visible')
  svg.setAttribute('style', 'vertical-align: text-bottom;')

  const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')
  path.setAttribute(
    'd',
    'm8.878.392 5.25 3.045c.54.314.872.89.872 1.514v6.098a1.75 1.75 0 0 1-.872 1.514l-5.25 3.045a1.75 1.75 0 0 1-1.756 0l-5.25-3.045A1.75 1.75 0 0 1 1 11.049V4.951c0-.624.332-1.2.872-1.514L7.122.392a1.75 1.75 0 0 1 1.756 0ZM7.875 1.69l-4.63 2.685L8 7.133l4.755-2.758-4.63-2.685a.248.248 0 0 0-.25 0ZM2.5 4.775v5.913c0 .09.047.171.125.216l4.625 2.683V7.653Zm6.25 8.832 4.625-2.683a.25.25 0 0 0 .125-.216V4.775L8.75 7.653Z'
  )

  svg.appendChild(path)
  return svg
}

// 创建 releases 按钮(带文本)
function createReleasesButton() {
  const el = document.querySelector('[class^="OverviewContent-module__Box_4"]')

  if (!el) {
    return
  }

  // 检查是否已经存在 releases 按钮
  if (el.querySelector('a[href*="/releases"]')) {
    return
  }

  // 创建按钮链接
  const a = document.createElement('a')
  a.type = 'button'
  a.href = `${window.location.pathname}/releases`
  a.className = 'prc-Button-ButtonBase-c50BI OverviewContent-module__Button--MDoYP'
  a.setAttribute('data-loading', 'false')
  a.setAttribute('data-size', 'medium')
  a.setAttribute('data-variant', 'invisible')

  // 创建按钮内容容器
  const buttonContent = document.createElement('span')
  buttonContent.setAttribute('data-component', 'buttonContent')
  buttonContent.setAttribute('data-align', 'center')
  buttonContent.className = 'prc-Button-ButtonContent-HKbr-'

  // 创建图标容器
  const visualWrap = document.createElement('span')
  visualWrap.setAttribute('data-component', 'leadingVisual')
  visualWrap.className = 'prc-Button-Visual-2epfX prc-Button-VisualWrap-Db-eB'

  const svg = createPackageIcon()
  visualWrap.appendChild(svg)

  // 创建文本标签
  const label = document.createElement('span')
  label.setAttribute('data-component', 'text')
  label.className = 'prc-Button-Label-pTQ3x'
  label.textContent = 'Releases'

  // 组装按钮
  buttonContent.appendChild(visualWrap)
  buttonContent.appendChild(label)
  a.appendChild(buttonContent)

  // 添加到容器
  el.appendChild(a)
}

// 创建 releases 按钮(仅图标)
function createReleasesButtonMobile() {
  const el = document.querySelector('[class^="OverviewContent-module__Box_5"]')

  if (!el) {
    return
  }

  // 检查是否已经存在 releases 按钮
  if (el.querySelector('a[href*="/releases"]')) {
    return
  }

  // 创建按钮链接
  const a = document.createElement('a')
  a.type = 'button'
  a.href = `${window.location.pathname}/releases`
  a.setAttribute('aria-label', 'Go to Releases page')
  a.className = 'prc-Button-ButtonBase-c50BI OverviewContent-module__Button_1--_1Ng2'
  a.setAttribute('data-loading', 'false')
  a.setAttribute('data-no-visuals', 'true')
  a.setAttribute('data-size', 'medium')
  a.setAttribute('data-variant', 'invisible')

  const svg = createPackageIcon()
  a.appendChild(svg)

  // 添加到容器
  el.appendChild(a)
}

function initButtons() {
  if (!isGithubRepo(window.location.pathname)) {
    return
  }

  createReleasesButton()
  createReleasesButtonMobile()
}

;(function () {
  'use strict'

  // 初始化
  initButtons()

  // 监听页面变化
  new MutationObserver(() => {
    // 检查两个容器是否存在
    if (
      document.querySelector('[class^="OverviewContent-module__Box_4"]') ||
      document.querySelector('[class^="OverviewContent-module__Box_5"]')
    ) {
      initButtons()
    }
  }).observe(document, {
    childList: true,
    subtree: true,
  })
})()