LKML ArticleBody 複製器

一鍵複製 lkml.org 文章區塊 <pre itemprop="articleBody"></pre> 純文字內容

目前為 2025-06-06 提交的版本,檢視 最新版本

// ==UserScript==
// @name         LKML ArticleBody 複製器
// @namespace    https://abc0922001.github.io/lkml-userscripts
// @version      1.0
// @description  一鍵複製 lkml.org 文章區塊 <pre itemprop="articleBody"></pre> 純文字內容
// @author       abc0922001
// @match        https://lkml.org/lkml/*/*/*/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
  'use strict';

  // 只等一次
  function waitForElement(selector, timeout = 4000) {
    return new Promise((resolve, reject) => {
      const el = document.querySelector(selector);
      if (el) return resolve(el);
      const observer = new MutationObserver(() => {
        const found = document.querySelector(selector);
        if (found) {
          observer.disconnect();
          resolve(found);
        }
      });
      observer.observe(document.body, { childList: true, subtree: true });
      setTimeout(() => {
        observer.disconnect();
        reject(new Error('Timeout'));
      }, timeout);
    });
  }

  function showToast(msg) {
    let toast = document.createElement('div');
    toast.textContent = msg;
    Object.assign(toast.style, {
      position: 'fixed',
      top: '16px',
      right: '16px',
      background: '#222',
      color: '#fff',
      padding: '8px 20px',
      borderRadius: '6px',
      fontSize: '15px',
      zIndex: 9999,
      opacity: 0.95,
      boxShadow: '0 2px 10px #0003',
      pointerEvents: 'none'
    });
    document.body.appendChild(toast);
    setTimeout(() => { toast.remove(); }, 1800);
  }

  function copyToClipboard(txt) {
    navigator.clipboard.writeText(txt)
      .then(() => showToast('✅ 已複製純文字內容'))
      .catch(err => showToast('❌ 複製失敗'));
  }

  function createCopyBtn() {
    let btn = document.createElement('button');
    btn.textContent = '📋 複製正文';
    Object.assign(btn.style, {
      position: 'fixed',
      top: '16px',
      right: '16px',
      zIndex: 10000,
      padding: '8px 14px',
      fontSize: '16px',
      background: '#2b7de9',
      color: '#fff',
      border: 'none',
      borderRadius: '6px',
      cursor: 'pointer',
      boxShadow: '0 1px 5px #0002'
    });
    btn.onclick = () => {
      const selector = 'pre[itemprop="articleBody"]';
      waitForElement(selector)
        .then(el => copyToClipboard(el.textContent.trim()))
        .catch(() => showToast('⚠️ 沒有找到正文'));
    };
    document.body.appendChild(btn);
  }

  createCopyBtn();
})();