您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a "Copy commit reference" button to every commit page on Gitea and Forgejo websites.
当前为
// ==UserScript== // @name Gitea: copy commit reference // @namespace https://andrybak.dev // @version 7 // @license AGPL-3.0-only // @author Andrei Rybak // @description Adds a "Copy commit reference" button to every commit page on Gitea and Forgejo websites. // @icon https://about.gitea.com/favicon.ico // @homepageURL https://github.com/rybak/copy-commit-reference-userscript // @supportURL https://github.com/rybak/copy-commit-reference-userscript/issues // @match https://gitea.com/*/commit/* // @match https://git.plastiras.org/*/commit/* // @match https://projects.blender.org/*/commit/* // @match https://codeberg.org/*/commit/* // @match https://next.forgejo.org/*/commit/* // @match https://code.forgejo.org/*/commit/* // @require https://cdn.jsdelivr.net/gh/rybak/userscript-libs@e86c722f2c9cc2a96298c8511028f15c45180185/waitForElement.js // @require https://cdn.jsdelivr.net/gh/rybak/copy-commit-reference-userscript@c7f2c3b96fd199ceee46de4ba7eb6315659b34e3/copy-commit-reference-lib.js // @grant none // ==/UserScript== /* * Copyright (C) 2023-2024 Andrei Rybak * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ (function () { 'use strict'; /** * Implementation for Gitea and its fork Forgejo. * * Example URLs for testing: * - https://git.plastiras.org/Tha_14/Antidote/commit/f84a08f1ac5312acc9ccedff25e6957e575f03ff * - https://codeberg.org/forgejo/forgejo/commit/e35d92de1f37bea0a593093678f093845955e3fc * - https://codeberg.org/forgejo/forgejo/commit/a4369782e1cfbbc6f588c0cda5776ee823b0e493 */ class Gitea extends GitHosting { getTargetSelector() { return '.commit-header h3 + div'; } wrapButtonContainer(container) { container.style.marginRight = '0.5rem'; return container; } wrapButton(button) { /* * Mimicking Gitea's "Browse Source" button, but without class 'primary', * because there shouldn't be too many primary buttons. Class 'basic' is * for styling like most of the buttons on the commit pages. */ button.classList.add('ui', 'tiny', 'button', 'basic'); const maybeNativeIcon = document.querySelector('.svg.octicon-copy'); if (maybeNativeIcon) { /* * Some instances of Gitea don't have the copy icons, * e.g. https://projects.blender.org */ const icon = maybeNativeIcon.cloneNode(true); icon.style.verticalAlign = 'middle'; icon.style.marginTop = '-4px'; button.insertBefore(document.createTextNode(" "), button.childNodes[0]); button.insertBefore(icon, button.childNodes[0]); } return button; } addButtonContainerToTarget(target, buttonContainer) { // to the left of Gitea's "Browse Source" button target.insertBefore(buttonContainer, target.querySelector('.ui.primary.tiny.button')); } /** * Styles adapted from GitHub's CSS classes ".tooltipped::before" * and ".tooltipped-s::before". * * @returns {HTMLElement} */ #createTooltipTriangle() { const triangle = document.createElement('div'); triangle.style.position = 'absolute'; triangle.style.zIndex = '1000001'; triangle.style.bottom = '-15px'; // not -16px to look better at different zoom levels triangle.style.left = '14px'; // to align with .left of `checkmark` triangle.style.height = '0'; triangle.style.width = '0'; /* * Borders connect at 45° angle => when only top border is colored, * it's a trapezoid. But with width=0, the bottom edge of trapezoid * has length 0, so it's a downwards triangle. * * bgColor from Gitea CSS classes */ triangle.style.border = '8px solid transparent'; triangle.style.borderTopColor = 'var(--color-tooltip-bg)'; return triangle; } createCheckmark() { const checkmark = super.createCheckmark(); checkmark.style.left = '0.2rem'; // to put emoji right above the button's icon checkmark.style.bottom = 'calc(100% + 1.2rem)'; // to mimic native tooltips shown above the buttons /* * Look and feel from CSS classes of Tippy -- a library (?) * used by Gitea. */ checkmark.style.zIndex = '9999'; checkmark.style.backgroundColor = 'var(--color-tooltip-bg)'; checkmark.style.color = 'var(--color-tooltip-text)'; checkmark.style.borderRadius = 'var(--border-radius)'; checkmark.style.fontSize = '1rem'; checkmark.style.padding = '.5rem 1rem'; checkmark.appendChild(this.#createTooltipTriangle()); return checkmark; } getFullHash() { const browseButton = document.querySelector('.commit-header h3 + div > a'); const lastSlashIndex = browseButton.href.lastIndexOf('/'); return browseButton.href.slice(lastSlashIndex + 1); } getDateIso(hash) { const timeTag = document.querySelector('#authored-time relative-time'); return timeTag.datetime.slice(0, 'YYYY-MM-DD'.length); } getCommitMessage(hash) { const subj = document.querySelector('.commit-summary').innerText; const bodyElement = document.querySelector('.commit-body'); if (!bodyElement) { return subj; } const body = bodyElement.childNodes[0].innerText; return subj + '\n\n' + body; } static #getIssuesUrl() { const oldUiElement = document.querySelector('.header-wrapper > .ui.tabs.container > .tabular.menu.navbar a[href$="/issues"]'); if (oldUiElement) { return oldUiElement.href; } return document.querySelector('.header-wrapper .navbar a[href$="/issues"], .secondary-nav .overflow-menu-items a[href$="/issues"]').href; } convertPlainSubjectToHtml(plainTextSubject, hash) { if (!plainTextSubject.includes('#')) { return plainTextSubject; } const issuesUrl = Gitea.#getIssuesUrl(); return plainTextSubject.replaceAll(/#([0-9]+)/g, `<a href="${issuesUrl}/\$1">#\$1</a>`); } } CopyCommitReference.runForGitHostings(new Gitea()); })();