谷歌学术自动复制 BiBTeX (Enhanced BibTeX Fetcher with Filtering and Highlighting)

Fetch and copy BibTeX citations from academic papers, with advanced filtering and highlighting

// ==UserScript==
// @name         谷歌学术自动复制 BiBTeX (Enhanced BibTeX Fetcher with Filtering and Highlighting)
// @namespace    http://tampermonkey.net/
// @version      1.03
// @description  Fetch and copy BibTeX citations from academic papers, with advanced filtering and highlighting
// @author       Apricity
// @match        https://scholar.google.com/*
// @match        https://scholar.googleusercontent.com/scholar.bib*
// @icon         https://scholar.google.com/favicon.ico
// @grant        GM_setClipboard
// @license      GNU GPLv3
// ==/UserScript==

(function () {
  "use strict";

  function copyToClipboard(text) {
    GM_setClipboard(text, "text");
  }

  function endsWithAny(strings, url) {
    for (var i = 0; i < strings.length; i++) {
      if (url.endsWith(strings[i])) {
        return true;
      }
    }
    return false;
  }

  function containsAny(strings, url) {
    for (var i = 0; i < strings.length; i++) {
      if (url.includes(strings[i])) {
        return true;
      }
    }
    return false;
  }

  function processEntries() {
    // Select all entries
    var entries = document.querySelectorAll(".gs_ri");

    // Iterate over each entry
    for (var i = 0; i < entries.length; i++) {
      var entry = entries[i];

      // Select the description element
      var description = entry.querySelector(".gs_a");

      // If the description exists and the URL ends with .edu, .de, .jp, or contains amazonaws, hide the entry
      if (
        description &&
        (endsWithAny([".edu", ".de", ".jp"], description.innerText) ||
          containsAny(
            ["amazonaws", "thetalkingmachines"],
            description.innerText
          ))
      ) {
        entry.parentNode.style.display = "none";
      }

      // If the description exists and the URL contains meethings, highlight the entry
      if (
        description &&
        containsAny(
          ["aclanthology.org", "openreview.net", "neurips.cc", "dl.acm.org"],
          description.innerText
        )
      ) {
        entry.parentNode.style.backgroundColor = "#e4efff";
      }
    }
  }

  if (window.location.href.includes("scholar.bib")) {
    // Wait for the BibTeX text to load, then copy it
    setTimeout(function () {
      var bibtexText = document.body.innerText;
      if (bibtexText) {
        copyToClipboard(bibtexText);
        alert("BibTeX citation copied to clipboard!");
      }
    }, 2000); // Adjust timing as needed
    return;
  }

  var logoLink = document.querySelector("#gs_hdr_lgo");
  if (logoLink && logoLink.href.includes("zh-CN")) {
    // Copy the first citation
    var observer = new MutationObserver(function (mutations) {
      mutations.forEach(function (mutation) {
        if (!mutation.addedNodes) return;

        for (var i = 0; i < mutation.addedNodes.length; i++) {
          var node = mutation.addedNodes[i];
          var citationDiv = node.querySelector(".gs_citr");
          if (citationDiv) {
            // Copy the first citation
            var citationText = citationDiv.textContent;
            copyToClipboard(citationText);
            alert("Citation copied to clipboard!");
          }
        }
      });
    });
  } else {
    observer = new MutationObserver(function (mutations) {
      mutations.forEach(function (mutation) {
        if (!mutation.addedNodes) return;

        for (var i = 0; i < mutation.addedNodes.length; i++) {
          var node = mutation.addedNodes[i];
          var bibtexButton = node.querySelector("#gs_citi a.gs_citi");
          if (bibtexButton) {
            window.location.href = bibtexButton.href;
            observer.disconnect();
            return;
          }
        }
      });
    });
  }

  processEntries();
  observer.observe(document.body, {
    childList: true,
    subtree: true,
  });
  var processObserver = new MutationObserver(processEntries);
  processObserver.observe(document.body, { childList: true, subtree: true });
})();