AI Grammar Checker (Grammarly Alternative) for Violentmonkey

Checks grammar and spelling in text inputs (Like Grammarly Premium!)

当前为 2025-02-13 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name AI Grammar Checker (Grammarly Alternative) for Violentmonkey
  3. // @namespace http://violentmonkey.net/
  4. // @version 1.2
  5. // @description Checks grammar and spelling in text inputs (Like Grammarly Premium!)
  6. // @author You
  7. // @match *://*/*
  8. // @grant GM_xmlhttpRequest
  9. // @connect api.languagetool.org
  10. // ==/UserScript==
  11.  
  12. var GrammarChecker = {};
  13.  
  14. GrammarChecker.API_URL = "https://api.languagetool.org/v2/check";
  15.  
  16. GrammarChecker.init = function() {
  17. console.log("🚀 Grammar Checker Loaded for Violentmonkey!");
  18.  
  19. // Observe text inputs and editable divs
  20. let observer = new MutationObserver(() => {
  21. document.querySelectorAll("textarea, input[type='text'], [contenteditable='true']").forEach(element => {
  22. if (!element.dataset.grammarChecked) {
  23. element.dataset.grammarChecked = "true";
  24. element.addEventListener("blur", () => GrammarChecker.checkGrammar(element));
  25. }
  26. });
  27. });
  28.  
  29. observer.observe(document.body, { childList: true, subtree: true });
  30. };
  31.  
  32. GrammarChecker.checkGrammar = function(element) {
  33. let text = element.value || element.innerText;
  34. if (!text.trim()) return;
  35.  
  36. console.log("📝 Checking grammar for:", text);
  37.  
  38. GM_xmlhttpRequest({
  39. method: "POST",
  40. url: GrammarChecker.API_URL,
  41. headers: { "Content-Type": "application/x-www-form-urlencoded" },
  42. data: `language=en-US&text=${encodeURIComponent(text)}`,
  43. onload: function(response) {
  44. if (response.status === 200) {
  45. let data = JSON.parse(response.responseText);
  46. GrammarChecker.showCorrections(element, data);
  47. } else {
  48. console.error("❌ API Error:", response.statusText);
  49. }
  50. },
  51. onerror: function(error) {
  52. console.error("❌ Network Error:", error);
  53. }
  54. });
  55. };
  56.  
  57. GrammarChecker.showCorrections = function(element, data) {
  58. let errors = data.matches;
  59. if (errors.length === 0) {
  60. console.log("✅ No errors found.");
  61. return;
  62. }
  63.  
  64. // Remove old tooltips
  65. document.querySelectorAll(".grammar-tooltip").forEach(e => e.remove());
  66.  
  67. let suggestions = errors.map(e => `${e.message} ${e.replacements.map(r => r.value).join(", ")}`).join("\n");
  68.  
  69. let tooltip = document.createElement("div");
  70. tooltip.className = "grammar-tooltip";
  71. tooltip.innerText = suggestions;
  72.  
  73. tooltip.style.position = "absolute";
  74. tooltip.style.background = "#fffa65";
  75. tooltip.style.color = "#333";
  76. tooltip.style.border = "1px solid #f39c12";
  77. tooltip.style.padding = "8px";
  78. tooltip.style.zIndex = "9999";
  79. tooltip.style.maxWidth = "300px";
  80. tooltip.style.fontSize = "14px";
  81. tooltip.style.top = `${element.getBoundingClientRect().bottom + window.scrollY}px`;
  82. tooltip.style.left = `${element.getBoundingClientRect().left}px`;
  83.  
  84. document.body.appendChild(tooltip);
  85.  
  86. setTimeout(() => tooltip.remove(), 5000);
  87. };
  88.  
  89. // Start the script
  90. GrammarChecker.init();
  91.  
  92.