GreasyFork Code: Syntax Highlight by CodeMirror

To syntax highlight GreasyFork Code by CodeMirror

Verze ze dne 17. 12. 2023. Zobrazit nejnovější verzi.

  1. // ==UserScript==
  2. // @name GreasyFork Code: Syntax Highlight by CodeMirror
  3. // @namespace Violentmonkey Scripts
  4. // @match https://greatest.deepsurf.us/*
  5. // @match https://sleazyfork.org/*
  6. // @grant none
  7. // @version 0.2.6
  8. // @author CY Fung
  9. // @description To syntax highlight GreasyFork Code by CodeMirror
  10. // @run-at document-start
  11. // @inject-into page
  12. // @unwrap
  13. // @license MIT
  14. // ==/UserScript==
  15.  
  16. (() => {
  17. let byPass = true;
  18.  
  19. let documentReady = new Promise(resolve => {
  20. Promise.resolve().then(() => {
  21. if (document.readyState !== 'loading') {
  22. resolve();
  23. } else {
  24. window.addEventListener("DOMContentLoaded", resolve, false);
  25. }
  26. });
  27. });
  28.  
  29. // Function to load CodeMirror library
  30. function loadCodeMirror(arr) {
  31.  
  32.  
  33. const promises = arr.map((href) => {
  34. return new Promise(resolve => {
  35.  
  36. const script = document.createElement('script');
  37. script.src = href;
  38. script.onload = () => {
  39. resolve(script);
  40. };
  41. document.head.appendChild(script);
  42.  
  43. });
  44.  
  45.  
  46. });
  47.  
  48. return Promise.all(promises);
  49. }
  50.  
  51. // Function to load CodeMirror CSS
  52. function loadCodeMirrorCSS(href) {
  53. const link = document.createElement('link');
  54. link.rel = 'stylesheet';
  55. link.href = href;
  56. document.head.appendChild(link);
  57. }
  58.  
  59. async function runBlock(codeBlock) {
  60.  
  61. let textarea = document.createElement('textarea');
  62. textarea.value = `${codeBlock.textContent}`;
  63. textarea.readOnly = true;
  64. textarea.id = 'editor651';
  65.  
  66.  
  67. // textarea.classList.add('code-container')
  68.  
  69. textarea.style.width = '100%';
  70. textarea.style.height = '100vh';
  71.  
  72.  
  73. codeBlock.replaceWith(textarea);
  74. codeBlock.remove();
  75.  
  76.  
  77. let editor651 = CodeMirror.fromTextArea(document.querySelector('#editor651'), {
  78.  
  79. mode: "javascript",
  80.  
  81. readOnly: true,
  82. styleActiveLine: true,
  83. lineNumbers: true,
  84. extraKeys: { "Alt-F": "findPersistent" }
  85. });
  86. editor651.save();
  87.  
  88.  
  89. }
  90.  
  91. // Main function to apply CodeMirror syntax highlighting to pre elements
  92. async function applyCodeMirrorSyntaxHighlighting() {
  93.  
  94. if (window.requestIdleCallback) await new Promise(r => !!window.requestIdleCallback(r));
  95. else {
  96. await new Promise(r => !!window.requestAnimationFrame(r));
  97. await new Promise(r => !!window.setTimeout(r, 170));
  98. await new Promise(r => !!window.requestAnimationFrame(r));
  99. }
  100.  
  101. const codeBlocks = document.querySelectorAll('pre.prettyprint.linenums.lang-js');
  102.  
  103.  
  104. // Check if CodeMirror is loaded
  105. if (typeof CodeMirror !== 'undefined') {
  106.  
  107. for (const codeBlock of codeBlocks) {
  108.  
  109. await new Promise((resolve) => {
  110.  
  111. let io = new IntersectionObserver(() => {
  112.  
  113. io.disconnect();
  114. io.takeRecords();
  115. io = null;
  116. resolve();
  117.  
  118.  
  119. })
  120.  
  121. io.observe(codeBlock);
  122.  
  123. });
  124.  
  125. await runBlock(codeBlock);
  126.  
  127.  
  128. }
  129.  
  130.  
  131.  
  132. } else {
  133. console.error('CodeMirror library is not loaded. Syntax highlighting cannot be applied.');
  134. }
  135. }
  136.  
  137. async function doAction() {
  138.  
  139. await new Promise(r => setTimeout(r, 1));
  140.  
  141. document.head.appendChild(document.createElement('style')).textContent = `
  142.  
  143. .code-container{
  144. height:100vh;
  145. }
  146. .code-container .CodeMirror, .code-container textarea{
  147. height:100%;
  148. }
  149. /*
  150. body {
  151. display: flex;
  152. flex-direction: column;
  153. height: 100vh;
  154. }
  155. body > div:last-child {
  156. height:0;
  157. flex-grow:1;
  158. display: flex;
  159. flex-direction:column;
  160. }
  161. body > div:last-child > #script-info:last-child {
  162. height:0;
  163. flex-grow:1;
  164. display: flex;
  165. flex-direction:column;
  166. }
  167. body > div:last-child > #script-info:last-child > #script-content:last-child {
  168. height:0;
  169. flex-grow:1;
  170. display: flex;
  171. flex-direction:column;
  172. gap:2px;
  173. }
  174. body > div:last-child > #script-info:last-child > #script-content:last-child > * {
  175. margin:0;
  176. }
  177. body > div:last-child > #script-info:last-child > #script-content:last-child > .code-container:last-child {
  178. height:0;
  179. flex-grow:1;
  180. display: flex;
  181. flex-direction:column;
  182. }
  183. body > div:last-child > #script-info:last-child > #script-content:last-child > .code-container:last-child > textarea:last-child {
  184. height:0;
  185. flex-grow:1;
  186. display: flex;
  187. flex-direction:column;
  188. }
  189. body > div:last-child > #script-info:last-child > #script-content:last-child > .code-container:last-child > .CodeMirror:last-child {
  190. height:0;
  191. flex-grow:1;
  192. display: flex;
  193. flex-direction:column;
  194. }
  195. */
  196. `;
  197.  
  198. await loadCodeMirror(['https://cdn.jsdelivr.net/npm/codemirror@5.65.15/lib/codemirror.min.js']);
  199.  
  200. await loadCodeMirror([
  201. 'https://cdn.jsdelivr.net/npm/codemirror@5.65.15/mode/javascript/javascript.min.js',
  202. 'https://cdn.jsdelivr.net/npm/codemirror@5.65.15/addon/selection/active-line.min.js',
  203.  
  204.  
  205. 'https://cdn.jsdelivr.net/npm/codemirror@5.65.15/addon/search/search.js',
  206. 'https://cdn.jsdelivr.net/npm/codemirror@5.65.15/addon/search/searchcursor.js',
  207. 'https://cdn.jsdelivr.net/npm/codemirror@5.65.15/addon/search/jump-to-line.js',
  208. 'https://cdn.jsdelivr.net/npm/codemirror@5.65.15/addon/dialog/dialog.js'
  209.  
  210. ]);
  211.  
  212. loadCodeMirrorCSS('https://cdn.jsdelivr.net/npm/codemirror@5.65.15/lib/codemirror.min.css');
  213. loadCodeMirrorCSS('https://cdn.jsdelivr.net/npm/codemirror@5.65.15/addon/dialog/dialog.css');
  214.  
  215. await Promise.all([new Promise(r => setTimeout(r, 60)), new Promise(r => window.requestAnimationFrame(r))]);
  216.  
  217.  
  218. byPass = false;
  219.  
  220. applyCodeMirrorSyntaxHighlighting();
  221.  
  222.  
  223.  
  224.  
  225.  
  226.  
  227. }
  228.  
  229.  
  230. let mgg = 0;
  231. async function mTz() {
  232. if (mgg) return;
  233. mgg = 1;
  234. documentReady.then(doAction);
  235. }
  236.  
  237.  
  238.  
  239. function getElementsByTagName(tag) {
  240.  
  241. if (byPass) {
  242. if (tag === 'pre' || tag === 'code' || tag === 'xmp') {
  243. if (location.pathname.endsWith('/code')) {
  244.  
  245. setTimeout(mTz, 10)
  246. return [];
  247. }
  248. }
  249. }
  250. return this.getElementsByTagName331(tag);
  251. }
  252.  
  253.  
  254.  
  255. HTMLElement.prototype.getElementsByTagName331 = HTMLElement.prototype.getElementsByTagName
  256. Document.prototype.getElementsByTagName331 = Document.prototype.getElementsByTagName
  257.  
  258. HTMLElement.prototype.getElementsByTagName = getElementsByTagName
  259. Document.prototype.getElementsByTagName = getElementsByTagName
  260.  
  261. /*
  262. let mz= function(evt){
  263.  
  264. if(evt && evt.type ==='readystatechange') return;
  265. return EventTarget.prototype.addEventListener.apply(this,arguments)
  266.  
  267. };
  268. window.addEventListener = mz
  269. document.addEventListener = mz;
  270. */
  271.  
  272.  
  273. documentReady.then(async () => {
  274.  
  275. if (location.pathname.endsWith('/code')) return;
  276.  
  277. byPass = false;
  278.  
  279. });
  280.  
  281. })();