// ==UserScript== // @name Cgit: copy commit reference // @namespace https://andrybak.dev // @version 5 // @license AGPL-3.0-only // @author Andrei Rybak // @description Adds a "Copy commit reference" button to every commit page on Cgit websites. // @icon https://git.zx2c4.com/cgit/plain/cgit.png // @homepageURL https://github.com/rybak/copy-commit-reference-userscript // @supportURL https://github.com/rybak/copy-commit-reference-userscript/issues // @match https://git.kernel.org/pub/scm/*/commit/* // @match https://git.zx2c4.com/*/commit/* // @match https://git.savannah.gnu.org/cgit/*/commit/* // @match https://cgit.freebsd.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@d4905c247fedb40932bf07eebf3bf4c838e8d3d7/copy-commit-reference-lib.js // @grant none // @downloadURL https://update.greasyfork.icu/scripts/476735/Cgit%3A%20copy%20commit%20reference.user.js // @updateURL https://update.greasyfork.icu/scripts/476735/Cgit%3A%20copy%20commit%20reference.meta.js // ==/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 . */ (function () { 'use strict'; /* * Implementation for cgit. * Documentation: * - https://git.zx2c4.com/cgit/about/ * * Example URLs for testing: * - https://git.kernel.org/pub/scm/git/git.git/commit/?h=main&id=1f0fc1db8599f87520494ca4f0e3c1b6fabdf997 * - https://git.kernel.org/pub/scm/git/git.git/commit/?h=v2.42.0&id=43c8a30d150ecede9709c1f2527c8fba92c65f40 */ class Cgit extends GitHosting { getTargetSelector() { return 'body > #cgit > .content > table.commit-info > tbody > tr:nth-child(3) td.sha1, body > #cgit > .content > table.commit-info > tbody > tr:nth-child(3) td.oid'; } wrapButtonContainer(innerContainer) { const container = document.createElement('span'); container.append(" (", innerContainer, ")"); return container; } getButtonText() { // use all lowercase for consistency with the rest of the UI return "copy commit reference"; } getFullHash() { const commitAnchor = document.querySelector('body > #cgit > .content > table.commit-info > tbody > tr:nth-child(3) td.sha1 a, body > #cgit > .content > table.commit-info > tbody > tr:nth-child(3) td.oid a'); return commitAnchor.innerText; } getDateIso(hash) { const authorDateCell = document.querySelector('body > #cgit > .content > table.commit-info > tbody > tr:nth-child(1) td:nth-child(3)'); return authorDateCell.innerText.slice(0, 'YYYY-MM-DD'.length); } getCommitMessage(hash) { const subjElem = document.querySelector('body > #cgit > .content > .commit-subject'); /* * Sometimes `subjElem` contains a ``, * most notably, on tagged commits. Avoid including the contents * of this tag by just taking the text of the first node, * which is a text node. */ const subj = subjElem.childNodes[0].textContent; const body = document.querySelector('body > #cgit > .content > .commit-msg').innerText; /* * Even though vast majority will only need `subj`, gather everything and * let downstream code handle paragraph splitting. */ return subj + '\n\n' + body; } } CopyCommitReference.runForGitHostings(new Cgit()); })();