iT邦幫忙

2025 iThome 鐵人賽

DAY 13
0
佛心分享-SideProject30

從零開始改善工作之 Chrome Extension: MR 通知文字小工具系列 第 13

Day 13 : 做個"按鈕",讓複製文字變得簡單

  • 分享至 

  • xImage
  •  

昨天我們把想要的文字初步組合出來,為了達到能更快速複製文字的目標,今天我們就把按鈕直接加到 Merge Request 頁面中吧!

回憶一下 Content Script

Content Script 可以:

  • 讀取或修改網頁的 DOM(像是在 MR 頁面抓標題、作者資訊)。
  • 傳送訊息給背景程式(Background/Service Worker)或 Popup 頁面。

我們可以在 Merge Request 頁面上注入按鈕,並綁定事件,觸發我們寫好的 generateReviewContent()。

實作(改寫 content_script.js)

  1. 我們新增一個新增 button 的 function

    • 找出想要放置按鈕的位子(這邊是放在 <h1> 之下,也可以放在自己喜歡的地方)。
    • 判斷該位置和按鈕是否有存在,位置存在且按鈕尚未被建立過,才能新增
    • 建立按鈕並為它添加一些 CSS (或是也可以透過 manifest.json 中的 content_script 設定指定要套用的 css 檔案)
    • 新增按鈕的點擊事件,這邊我們把取得文字從 MutationObserver 移過來,因為我們的按鈕會在 DOM 都載入完成之後再注入,就可避免抓不到數值的問題了
    • 將取得的文字丟到昨天寫好的 function 中
    • 最後將組合好的文字複製到剪貼簿上
    async function addCopyBtn() {
        const header = document.querySelector('h1');
        const currentCopyBtn = document.getElementById('mrCopyBtn');
    
        // 有 Header 且未建立按鈕才要建立
        if (header && !currentCopyBtn) {
            // 建立按鈕
            const btn = document.createElement('button');
            btn.id = 'mrCopyBtn';
            btn.textContent = '📋 複製 MR 訊息';
            btn.style.padding = '4px 0 0';
            btn.style.color = '#172B4D';
            btn.style.backgroundColor = 'transparent';
            btn.style.border = 'none';
    
            // 監聽按鈕點擊事件
            btn.addEventListener('click', async () => {
                // 取得 MR 資料
                const titleEl = document.querySelector(".title")
                    || document.querySelector("[data-testid='title-content']")
                    || document.querySelector("h1");
                const reviewerEl = document.querySelector("[data-testid='reviewer'] div");
                const title = titleEl.innerText.trim()
                const reviewer = reviewerEl.innerText.trim()
                const message = await generateReviewContent(title, reviewer);
                console.log(message);
    
                // 複製文字到剪貼簿
                navigator.clipboard.writeText(message).then(() => {
                    alert('MR 通知文字已複製!');
                });
            });
    
            // 將按鈕加到標題下方
            header.parentElement.insertAdjacentElement('afterend', btn);
        }
    }
    
  2. 將 MutationObserver 改寫成注入按鈕

        const targetNode = document.body;
        const config = { childList: true, subtree: true };
    
        const callback = (mutations) => {
            const isChildListChanged = mutations.some((mutation) =>
                mutation.type === 'childList' && mutation.addedNodes.length > 0
            );
    
            if (isChildListChanged) {
                observer.disconnect();  // 抓到就停止監聽,避免浪費效能
                addCopyBtn();
                observer.observe(targetNode, config);
            }
        }
    

(3. 如果昨天跟我一樣 return 要記得,才能抓到文字複製到剪貼簿)

```
    const observer = new MutationObserver(callback);
    observer.observe(targetNode, config);

    async function generateReviewContent(title, reviewer) {
        const {
            reviewTemplate
        } = await chrome.storage.sync.get(['reviewTemplate']);

        const reviewerNameSymbol = "{REVIEWER_NAME}";
        const mrLinkSymbol = "{MR_LINK}";

        const textContent = reviewTemplate
            .replace(reviewerNameSymbol, reviewer)
            .replace(mrLinkSymbol, title)

        return textContent //新增
    }
```

實際測試

  • 打開一個 GitLab Merge Request 頁面
  • 等待畫面是否有出現按鈕
    https://ithelp.ithome.com.tw/upload/images/20250922/20153928ur6shYDgw9.png
  • 點選按鈕是否有跳出複製成功文字
    https://ithelp.ithome.com.tw/upload/images/20250922/20153928DJc1pC5zNO.png
  • 檢查剪貼簿是否有複製成功
    https://ithelp.ithome.com.tw/upload/images/20250922/20153928WXtPcziTnc.png

上一篇
Day 12 : 將取得的資訊整理成我們要的通知文字吧!
下一篇
Day 14 : 僅使用 navigator.clipboard 和搭配 new ClipboardItem 的差別
系列文
從零開始改善工作之 Chrome Extension: MR 通知文字小工具15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言