LKML 內文複製器

一鍵複製 lkml.org 信件正文(<pre itemprop="articleBody">)。

当前为 2025-06-06 提交的版本,查看 最新版本

// ==UserScript==
// @name         LKML 內文複製器
// @namespace    https://abc0922001.github.io/lkml-copy
// @version      1.0
// @description  一鍵複製 lkml.org 信件正文(<pre itemprop="articleBody">)。
// @author       abc0922001
// @match        https://lkml.org/lkml/*
// @grant        none
// @license      MIT
// ==/UserScript==

(() => {
  'use strict';

  /* 等待元素工具 */
  const waitFor = (sel, timeout = 5000) =>
    new Promise((ok, ng) => {
      const hit = () => document.querySelector(sel);
      if (hit()) return ok(hit());
      const ob = new MutationObserver(() => hit() && (ob.disconnect(), ok(hit())));
      ob.observe(document.body, { childList: true, subtree: true });
      setTimeout(() => (ob.disconnect(), ng(new Error('timeout'))), timeout);
    });

  /* 提示 */
  const alertMsg = m => window.alert(m);

  /* 寫剪貼簿 */
  const copy = txt =>
    navigator.clipboard.writeText(txt)
      .then(() => alertMsg('✅  已複製到剪貼簿!'))
      .catch(e => alertMsg('❌  複製失敗:' + e.message));

  /* 建按鈕 */
  const btn = document.createElement('button');
  btn.textContent = '📋 複製信件';
  Object.assign(btn.style, {
    position: 'fixed', top: '10px', right: '10px', zIndex: 1000,
    padding: '6px 10px', fontSize: '14px',
    background: '#2b7de9', color: '#fff', border: 'none',
    borderRadius: '4px', cursor: 'pointer'
  });
  btn.onclick = () =>
    waitFor('pre[itemprop="articleBody"]')
      .then(el => copy(el.textContent))     /* 要 HTML 就改成 el.innerHTML */
      .catch(() => alertMsg('⚠️  找不到內文區塊。'));

  document.body.appendChild(btn);
})();