SpaceFrontiers Copier

Tự động gắn link DOI và thêm nút copy (gồm text + hyperlink) cho các khối markdown trên SpaceFrontiers.org

// ==UserScript==
// @name         SpaceFrontiers Copier
// @namespace    https://greasyfork.org/
// @version      1.0
// @description  Tự động gắn link DOI và thêm nút copy (gồm text + hyperlink) cho các khối markdown trên SpaceFrontiers.org
// @author       Bui Quoc Dung
// @match        https://spacefrontiers.org/*
// @grant        none
// ==/UserScript==

(function () {
  'use strict';

  // === GẮN LINK DOI ===
  const doiObserver = new MutationObserver(() => {
    document.querySelectorAll('span.reference-marker:not([data-doi-processed])').forEach(marker => {
      marker.setAttribute('data-doi-processed', 'true');
      const popoverId = marker.getAttribute('data-popover-target');
      const popover = document.querySelector(`#${popoverId}`);
      if (!popover) return;

      setTimeout(() => {
        const doiLink = popover.querySelector('a[href*="doi.org"]');
        if (doiLink) {
          const href = doiLink.href;
          const newLink = document.createElement('a');
          newLink.href = href;
          newLink.target = '_blank';
          newLink.rel = 'noopener noreferrer';
          newLink.innerHTML = marker.innerHTML;
          newLink.className = marker.className;
          marker.replaceWith(newLink);
        }
      }, 300);
    });
  });

  doiObserver.observe(document.body, { childList: true, subtree: true });

  // === NÚT COPY MARKDOWN (text + hyperlink HTML) ===
  const markdownObserver = new MutationObserver(() => {
    document.querySelectorAll('div.markdown:not([data-copy-added])').forEach(div => {
      div.setAttribute('data-copy-added', 'true');

      // Tạo nút copy
      const button = document.createElement('button');
      button.textContent = 'Copy';
      button.style.cssText = `
        position: absolute;
        top: 5px;
        right: 5px;
        background: #4caf50;
        color: white;
        border: none;
        padding: 4px 8px;
        border-radius: 4px;
        cursor: pointer;
        font-size: 14px;
        z-index: 999;
      `;

      // Tạo wrapper để chèn nút vào cùng khối
      const wrapper = document.createElement('div');
      wrapper.style.position = 'relative';
      div.parentNode.insertBefore(wrapper, div);
      wrapper.appendChild(div);
      wrapper.appendChild(button);

      // Xử lý sự kiện copy
      button.addEventListener('click', () => {
        const html = div.innerHTML;
        const text = div.innerText;

        const blob = new Blob([html], { type: 'text/html' });
        const data = [new ClipboardItem({
          'text/html': blob,
          'text/plain': new Blob([text], { type: 'text/plain' })
        })];

        navigator.clipboard.write(data).then(() => {
          button.textContent = 'Coping';
          setTimeout(() => (button.textContent = 'Copy'), 1500);
        }).catch(err => {
          console.error('Clipboard write failed', err);
          alert('❌ Copy failed: ' + err);
        });
      });
    });
  });

  markdownObserver.observe(document.body, { childList: true, subtree: true });
})();