GitHub Repo Markdown Link Copier

Add a copy button to GitHub repos to copy the repo link in markdown format

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         GitHub Repo Markdown Link Copier
// @namespace    https://dvel.me/github-repo-markdown-link-copier
// @version      1.0
// @description  Add a copy button to GitHub repos to copy the repo link in markdown format
// @author       Dvel
// @match        https://github.com/*/*
// @grant        GM_setClipboard
// ==/UserScript==

(function() {
    'use strict';

    // SVG图标
    const copyIconSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg>`;
    const checkedIconSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check2" viewBox="0 0 16 16"><path d="M13.854 3.646a.5.5 0 0 0-.708 0L7 9.793 3.854 6.646a.5.5 0 1 0-.708.708l3.5 3.5a.5.5 0 0 0 .708 0l6.5-6.5a.5.5 0 0 0 0-.708z"/></svg>`;

    // 使用MutationObserver监听DOM变化
    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            if (mutation.addedNodes.length > 0 || mutation.type === 'childList') {
                const navList = document.querySelector('nav[role="navigation"][aria-label="Page context"] ul');
                const existingButton = document.querySelector('#custom-copy-button');
                if (navList && !existingButton) {
                    addCopyButton();
                }
            }
        });
    });

    // 观察器配置:观察子节点的变化
    const config = { childList: true, subtree: true };

    // 监听页面加载事件,然后开始观察DOM变化
    window.addEventListener('load', () => {
        observer.observe(document.body, config);
    });

    function addCopyButton() {
        // 定位到GitHub页面导航栏的ul元素
        const navList = document.querySelector('nav[role="navigation"][aria-label="Page context"] ul');
        if (!navList) return;

        // 获取仓库的用户名和名称
        const pathParts = document.location.pathname.split('/').filter(Boolean);
        const repoFullName = document.location.pathname.substring(1);
        const repoUrl = window.location.href;


        // 创建按钮和设置样式
        const listItem = document.createElement('li');
        listItem.id = 'custom-copy-button'; // 确保按钮唯一性
        const copyButton = document.createElement('button');
        copyButton.innerHTML = `${copyIconSVG} Copy`;
        styleButton(copyButton); // 应用样式

        // 点击按钮复制Markdown链接
        copyButton.onclick = function() {
            const markdownLink = `[${pathParts[0]}/${pathParts[1]}](${repoUrl})`;
            GM_setClipboard(markdownLink);
            copyButton.innerHTML = `${checkedIconSVG} Copied!`;
            setTimeout(() => { copyButton.innerHTML = `${copyIconSVG} copy`; }, 10000);
        };

        listItem.appendChild(copyButton);
        navList.appendChild(listItem);
    }

    // 应用按钮样式,模仿GitHub风格
    function styleButton(button) {
        button.style.padding = '5px 10px';
        button.style.fontSize = '12px';
        button.style.fontWeight = '600';
        button.style.lineHeight = '20px';
        button.style.color = '#24292e';
        button.style.backgroundColor = '#eff3f6';
        button.style.border = '1px solid rgba(27,31,35,.15)';
        button.style.borderRadius = '6px';
        button.style.cursor = 'pointer';
        button.style.marginLeft = '8px';
        button.style.display = 'flex';
        button.style.alignItems = 'center';
        button.style.gap = '5px';

        button.onmouseover = function() {
            this.style.backgroundColor = '#e1e4e8';
        };
        button.onmouseout = function() {
            this.style.backgroundColor = '#eff3f6';
        };
    }
})();