Copy HTML to Anki

Copy specific parts of HTML text and send them to Anki, converting relative URLs to absolute URLs. Trigger with Ctrl+Shift+Y or via Tampermonkey menu.

Per 15-07-2024. Zie de nieuwste versie.

// ==UserScript==
// @name         Copy HTML to Anki
// @namespace    http://tampermonkey.net/
// @version      2.5
// @description  Copy specific parts of HTML text and send them to Anki, converting relative URLs to absolute URLs. Trigger with Ctrl+Shift+Y or via Tampermonkey menu.
// @author       nabe
// @match        *://*/*
// @grant        GM_xmlhttpRequest
// @grant        GM_registerMenuCommand
// @connect      localhost
// @run-at       document-end
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    function copyHtmlToAnki() {
        // Function to convert relative URLs to absolute URLs
        function makeAbsolute(url) {
            return new URL(url, document.baseURI).href;
        }

        // Clone the document to manipulate it
        let docClone = document.documentElement.cloneNode(true);

        // Convert all relative URLs to absolute URLs
        let elements = docClone.querySelectorAll('[src], [href]');
        elements.forEach(function(element) {
            if (element.hasAttribute('src')) {
                element.setAttribute('src', makeAbsolute(element.getAttribute('src')));
            }
            if (element.hasAttribute('href')) {
                element.setAttribute('href', makeAbsolute(element.getAttribute('href')));
            }
        });

        // Extract the text content of specific parts needed
        let questionElement = docClone.querySelector('.container.card');
        let questionField = questionElement ? questionElement.innerHTML : '';

        let hintField = Array.from(docClone.querySelectorAll('.options'))
                             .map(option => option.innerText.trim())
                             .filter(text => text)
                             .join('<br>') || '';

        let answerField = Array.from(docClone.querySelectorAll('.options.correct'))
                               .map(option => option.innerText.trim())
                               .filter(text => text)
                               .join('<br>') || '';

        let additionalInfoField = docClone.querySelector('.feedback')?.innerText.trim() || '';

        // Create the note fields
        let noteFields = {
            "Front": questionField,
            "Options": hintField,
            "Back": answerField,
            "Extra": additionalInfoField
        };

        console.log("Note fields extracted:", noteFields);

        GM_xmlhttpRequest({
            method: "POST",
            url: "http://localhost:8765",
            data: JSON.stringify({
                "action": "addNote",
                "version": 6,
                "params": {
                    "note": {
                        "deckName": "Default",
                        "modelName": "Basic Build",
                        "fields": noteFields,
                        "tags": ["newimport"]
                    }
                }
            }),
            headers: {
                "Content-Type": "application/json"
            },
            onload: function(response) {
                console.log("Response from AnkiConnect:", response);
                if (response.status === 200) {
                    console.log("Note fields sent to Anki!");
                } else {
                    alert("Failed to send note fields to Anki.");
                }
            }
        });
    }

    // Add event listener for the keyboard shortcut (Ctrl+Shift+Y)
    document.addEventListener('keydown', function(event) {
        if (event.ctrlKey && event.shiftKey && event.code === 'KeyY') {
            copyHtmlToAnki();
        }
    });

    // Register the menu command to Tampermonkey menu
    GM_registerMenuCommand("Copy HTML to Anki", copyHtmlToAnki);
})();