LeetCode Turbo

Replace monaco with vanilla textarea.

As of 2023-11-14. See the latest version.

  1. // ==UserScript==
  2. // @name LeetCode Turbo
  3. // @description Replace monaco with vanilla textarea.
  4. // @namespace https://greatest.deepsurf.us/users/197529
  5. // @version 0.1.2
  6. // @author kkocdko
  7. // @license Unlicense
  8. // @match *://leetcode.com/problems/*
  9. // @match *://leetcode.cn/problems/*
  10. // @run-at document-start
  11. // ==/UserScript==
  12. "use strict";
  13.  
  14. const globalThis = this.unsafeWindow || this;
  15. const originFetch = globalThis.fetch;
  16. const textarea = document.createElement("textarea");
  17. textarea.style =
  18. "font-family: monospace; height: 100%; width: 100%; padding: 6px 10px; white-space: pre; outline: none;";
  19. const replaceEditorTimer = setInterval(() => {
  20. try {
  21. document.querySelector("#editor").replaceWith(textarea);
  22. clearInterval(replaceEditorTimer);
  23. } catch (_) {}
  24. }, 500);
  25. globalThis.fetch = (input, init) => {
  26. if (input?.includes("/lc-monaco/") || input?.includes("/monaco-tm/")) {
  27. throw Error("Monaco editor blocked.");
  28. }
  29. if (input?.endsWith("/submit") || input?.endsWith("/submit/")) {
  30. init.body = JSON.stringify({
  31. ...JSON.parse(init.body),
  32. typed_code: textarea.value,
  33. });
  34. }
  35. return originFetch(input, init);
  36. };
  37. const titleSlug = location.href.split("/problems/")[1].split("/")[0];
  38. fetch("https://leetcode.cn/graphql/", {
  39. headers: { "content-type": "application/json" },
  40. method: "POST",
  41. body: JSON.stringify({
  42. operationName: "questionEditorData",
  43. variables: { titleSlug },
  44. query: `
  45. query questionEditorData($titleSlug: String!) {
  46. question(titleSlug: $titleSlug) {
  47. codeSnippets {
  48. langSlug
  49. code
  50. }
  51. }
  52. }
  53. `,
  54. }),
  55. })
  56. .then((v) => v.json())
  57. .then((v) => {
  58. textarea.value = v.data.question.codeSnippets.find(
  59. (v) => v.langSlug == "cpp"
  60. ).code;
  61. });
  62.  
  63. // more conservative requestAnimationFrame
  64. // const originRequestAnimationFrame = globalThis.requestAnimationFrame;
  65. // let rafCounter = 0;
  66. // let rafBoost = false;
  67. // globalThis.addEventListener("pointermove", () => {
  68. // rafBoost = true;
  69. // });
  70. // globalThis.requestAnimationFrame = (callback) => {
  71. // // if (rafBoost || rafCounter === 0) {
  72. // originRequestAnimationFrame(callback);
  73. // // } else {
  74. // setTimeout(() => {
  75. // originRequestAnimationFrame(callback);
  76. // }, 900);
  77. // // }
  78. // rafCounter = (rafCounter + 1) % 4;
  79. // };
  80.  
  81. // https://leetcode.cn/problems/intersection-of-two-arrays-ii/description/
  82.  
  83. // ublock append ||static.leetcode.cn/lc-monaco/
  84.  
  85. /*
  86. fetch("https://leetcode.cn/graphql/", {
  87. headers: { "content-type": "application/json" },
  88. method: "POST",
  89. body: JSON.stringify({
  90. query:
  91. "\n query questionTitle($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n questionId\n questionFrontendId\n title\n titleSlug\n isPaidOnly\n difficulty\n likes\n dislikes\n categoryTitle\n }\n}\n ",
  92. variables: { titleSlug: "intersection-of-two-arrays-ii" },
  93. operationName: "questionTitle",
  94. }),
  95. })
  96. .then((v) => v.text())
  97. .then((v) => console.log(v));
  98.  
  99. // 获取预设代码片段
  100. fetch("https://leetcode.cn/graphql/", {
  101. headers: { "content-type": "application/json" },
  102. method: "POST",
  103. body: JSON.stringify({
  104. query:
  105. "\n query questionEditorData($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n questionId\n questionFrontendId\n codeSnippets {\n lang\n langSlug\n code\n }\n envInfo\n enableRunCode\n hasFrontendPreview\n frontendPreviews\n }\n}\n ",
  106. variables: { titleSlug: "intersection-of-two-arrays-ii" },
  107. operationName: "questionEditorData",
  108. }),
  109. })
  110. .then((v) => v.json())
  111. .then((v) => console.log(v));
  112.  
  113. fetch("https://leetcode.cn/graphql/", {
  114. headers: { "content-type": "application/json" },
  115. method: "POST",
  116. body: JSON.stringify({
  117. query:
  118. "\n query questionContent($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n content\n editorType\n mysqlSchemas\n dataSchemas\n }\n}\n ",
  119. variables: { titleSlug: "intersection-of-two-arrays-ii" },
  120. operationName: "questionContent",
  121. }),
  122. });
  123.  
  124. fetch("https://leetcode.cn/graphql/", {
  125. headers: { "content-type": "application/json" },
  126. method: "POST",
  127. body: JSON.stringify({
  128. query:
  129. "\n query questionTranslations($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n translatedTitle\n translatedContent\n }\n}\n ",
  130. variables: { titleSlug: "intersection-of-two-arrays-ii" },
  131. operationName: "questionTranslations",
  132. }),
  133. });
  134. */