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.

目前為 2024-07-16 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Copy HTML to Anki
  3. // @namespace http://tampermonkey.net/
  4. // @version 3.1
  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.
  6. // @author nabe
  7. // @match *://*/*
  8. // @grant GM_xmlhttpRequest
  9. // @grant GM_registerMenuCommand
  10. // @connect localhost
  11. // @run-at document-end
  12. // @license MIT
  13. // ==/UserScript==
  14. (function() {
  15. 'use strict';
  16. function copyHtmlToAnki() {
  17. // Function to convert relative URLs to absolute URLs
  18. function makeAbsolute(url) {
  19. return new URL(url, document.baseURI).href;
  20. }
  21. // Clone the document to manipulate it
  22. let docClone = document.documentElement.cloneNode(true);
  23. // Convert all relative URLs to absolute URLs
  24. let elements = docClone.querySelectorAll('[src], [href]');
  25. elements.forEach(function(element) {
  26. if (element.hasAttribute('src')) {
  27. element.setAttribute('src', makeAbsolute(element.getAttribute('src')));
  28. }
  29. if (element.hasAttribute('href')) {
  30. element.setAttribute('href', makeAbsolute(element.getAttribute('href')));
  31. }
  32. });
  33. // Extract the text content of specific parts needed
  34. let frontElement = docClone.querySelector('.container.card');
  35. let frontField = frontElement ? frontElement.innerHTML : '';
  36. console.log("Front Field:", frontField);
  37.  
  38. // If frontElement is empty, capture content from .photo-question
  39. if (!frontField) {
  40. let photoQuestionElement = docClone.querySelector('.solution.container .photo-question');
  41. frontField = photoQuestionElement ? photoQuestionElement.outerHTML : '';
  42. }
  43. console.log("Front Field:", frontField);
  44.  
  45. let questionField = docClone.querySelector('form.question h3')?.innerText.trim() || '';
  46. console.log("Question Field:", questionField);
  47. let optionField = Array.from(docClone.querySelectorAll('.options .option'))
  48. .map(option => option.innerText.trim())
  49. .filter(text => text)
  50. .map(text => `<li>${text}</lis>`)
  51. .join('') || '';
  52. console.log("Option Field:", optionField);
  53. let backField = Array.from(docClone.querySelectorAll('.options .option.correct'))
  54. .map(option => option.innerText.trim())
  55. .filter(text => text)
  56. .map(text => `<li>${text}</li>`)
  57. .join('') || '';
  58. console.log("Answer Field:", backField);
  59. //let extraField = docClone.querySelector('.results.container.collected .feedback-container .text')?.innerText.trim() || '';
  60. //console.log("Additional Info Field:", extraField);
  61. let extraElement = docClone.querySelector('.results.container.collected .feedback-container .text');
  62. let extraField = extraElement ? extraElement.innerHTML : '';
  63. console.log("Additional Info Field:", extraField);
  64.  
  65.  
  66. // Create the note fields
  67. let noteFields = {
  68. "Front": frontField,
  69. "Question": questionField,
  70. "Options": optionField,
  71. "Back": backField,
  72. "Extra": extraField
  73. };
  74. console.log("Note fields to be sent to Anki:", noteFields);
  75. GM_xmlhttpRequest({
  76. method: "POST",
  77. url: "http://localhost:8765",
  78. data: JSON.stringify({
  79. "action": "addNote",
  80. "version": 6,
  81. "params": {
  82. "note": {
  83. "deckName": "Default",
  84. "modelName": "Basic Build",
  85. "fields": noteFields,
  86. "tags": ["newimport"]
  87. }
  88. }
  89. }),
  90. headers: {
  91. "Content-Type": "application/json"
  92. },
  93. onload: function(response) {
  94. console.log("Response from AnkiConnect:", response);
  95. if (response.status === 200) {
  96. console.log("Note fields sent to Anki successfully!");
  97. } else {
  98. console.error("Failed to send note fields to Anki.");
  99. }
  100. }
  101. });
  102. }
  103. // Add event listener for the keyboard shortcut (Ctrl+Shift+Y)
  104. document.addEventListener('keydown', function(event) {
  105. if (event.ctrlKey && event.shiftKey && event.code === 'KeyY') {
  106. copyHtmlToAnki();
  107. }
  108. });
  109. // Register the menu command to Tampermonkey menu
  110. GM_registerMenuCommand("Copy HTML to Anki", copyHtmlToAnki);
  111. })();