NotebookLM shows all citations

Automatically appends source info in NotebookLM

// ==UserScript==
// @name         NotebookLM shows all citations
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Automatically appends source info in NotebookLM
// @author       Bui Quoc Dung
// @match        https://notebooklm.google.com/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    const delay = ms => new Promise(res => setTimeout(res, ms));

    async function processHover(button) {
        if (button.dataset.processed === "true") return;
        button.dataset.processed = "true";

        // Hover to show popup
        const mouseOver = new MouseEvent("mouseover", { bubbles: true, cancelable: true });
        const mouseEnter = new MouseEvent("mouseenter", { bubbles: true, cancelable: true });
        button.dispatchEvent(mouseOver);
        button.dispatchEvent(mouseEnter);

        await delay(700); // Wait for popup to render

        // Find popup that contains .pdf file
        const pdfDivs = Array.from(document.querySelectorAll('.citation-tooltip-footer'))
            .filter(el => el.textContent.trim().toLowerCase().endsWith('.pdf'));

        if (pdfDivs.length > 0) {
            const lastPdfText = pdfDivs[pdfDivs.length - 1].textContent.trim();
            const span = button.querySelector('span');
            if (span && !span.textContent.includes(lastPdfText)) {
                span.textContent += ` (${lastPdfText})`;
            }
        }

        // Move mouse out
        const mouseLeave = new MouseEvent("mouseleave", { bubbles: true, cancelable: true });
        button.dispatchEvent(mouseLeave);
        await delay(100);
    }

    async function processAllCitations() {
        const buttons = document.querySelectorAll('button.citation-marker');
        for (const button of buttons) {
            await processHover(button);
        }
    }

    const observer = new MutationObserver(() => {
        processAllCitations();
        insertCopyAllButtons();
    });

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

    processAllCitations();
    insertCopyAllButtons();
})();