GreasyFork Code: Monaco Editor

12/17/2023, 2:31:22 PM

当前为 2023-12-17 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name GreasyFork Code: Monaco Editor
  3. // @namespace Violentmonkey Scripts
  4. // @match https://greasyfork.org/*
  5. // @grant none
  6. // @version 0.1.3
  7. // @author CY Fung
  8. // @description 12/17/2023, 2:31:22 PM
  9. // @run-at document-start
  10. // @unwrap
  11. // @license MIT
  12. // ==/UserScript==
  13.  
  14. // localStorage.darkMode = 'true'
  15. // localStorage.autoMonacoEditor = 'true'
  16.  
  17. (() => {
  18.  
  19. const cssText01 = `
  20. .monaco-editor-container{
  21. margin: 0;
  22. padding: 0;
  23. box-sizing: border-box;
  24. display: none;
  25. }
  26. [monaco-editor-status="1"] .monaco-editor-container{
  27. display: block;
  28. }
  29. [monaco-editor-status="1"] .monaco-controlled-textarea{
  30. display: none;
  31. }
  32. [monaco-editor-status="2"] .monaco-editor-container{
  33. display: none;
  34. }
  35. [monaco-editor-status="2"] .monaco-controlled-textarea{
  36. display: block;
  37. }
  38. `;
  39.  
  40. const elmSet = {};
  41.  
  42. HTMLInputElement.prototype.addEventListener177 = HTMLInputElement.prototype.addEventListener;
  43. HTMLInputElement.prototype.addEventListener = function () {
  44. if (arguments.length === 2 && arguments[0] === 'change' && (arguments[1] || 0).name === 'handleChange') {
  45. // if(this === ) return;
  46. // console.log(this)
  47. if (this.id === 'enable-source-editor-code') return;
  48. // return;
  49. }
  50. return this.addEventListener177.apply(this, arguments);
  51.  
  52. }
  53.  
  54.  
  55. function loadResource(type, url) {
  56. if (type === 'css') {
  57. return new Promise(resolve => {
  58. var link = document.createElement('link');
  59. var onload = function () {
  60. link.removeEventListener('load', onload, false);
  61. resolve();
  62. }
  63. link.addEventListener('load', onload, false);
  64. link.rel = 'stylesheet';
  65. link.href = url;
  66. document.head.appendChild(link);
  67. });
  68. } else if (type === 'js') {
  69. return new Promise(resolve => {
  70. var script = document.createElement('script');
  71. var onload = function () {
  72. script.removeEventListener('load', onload, false);
  73. resolve();
  74. }
  75. script.addEventListener('load', onload, false);
  76. script.src = url;
  77. document.head.appendChild(script);
  78. })
  79. }
  80. }
  81.  
  82. function onChange817(e) {
  83.  
  84.  
  85.  
  86. // console.log(123213)
  87.  
  88. const target = (e || 0).target || null;
  89.  
  90. if (!target) return;
  91.  
  92. let monacoStatus = target.getAttribute('monaco-status')
  93. if (monacoStatus) {
  94.  
  95. e.stopImmediatePropagation();
  96. e.stopPropagation();
  97. e.preventDefault();
  98.  
  99. const textAreaParent = elmSet.textAreaParent;
  100. const textArea = elmSet.textArea;
  101. const editor = elmSet.editor;
  102.  
  103. // console.log(monacoStatus)
  104. if (monacoStatus === '1') {
  105. // elmSet.container.replaceWith(elmSet.textArea);
  106.  
  107.  
  108.  
  109. textAreaParent.setAttribute('monaco-editor-status', '2')
  110. target.setAttribute('monaco-status', monacoStatus = '2')
  111. return;
  112.  
  113. } else if (monacoStatus === '2') {
  114.  
  115. // elmSet.textArea.replaceWith(elmSet.container);
  116.  
  117. const currentCode = editor.getValue();
  118. const currentText = textArea.value;
  119. if (currentCode !== currentText) {
  120. editor.setValue(currentText);
  121. }
  122.  
  123. textAreaParent.setAttribute('monaco-editor-status', '1')
  124. target.setAttribute('monaco-status', monacoStatus = '1')
  125. return;
  126. } else {
  127. return;
  128. }
  129.  
  130. }
  131.  
  132. const codeId = target.getAttribute('data-related-editor') || '';
  133. if (!codeId) return;
  134.  
  135. const textArea = document.getElementById(codeId);
  136.  
  137. if (!textArea) return;
  138.  
  139. const codeLang = target.getAttribute('data-editor-language'); // 'javascript', 'css'
  140.  
  141. if (!codeLang) return;
  142.  
  143.  
  144. target.setAttribute('monaco-status', '1');
  145.  
  146.  
  147. e.stopImmediatePropagation();
  148. e.stopPropagation();
  149. e.preventDefault();
  150.  
  151.  
  152. const vsPath = "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.45.0/min/vs"
  153. // Setting up Monaco Editor requirements
  154. var require = {
  155. paths: {
  156. vs: vsPath,
  157. },
  158. };
  159. window.require = require;
  160.  
  161.  
  162. const addCssText = (id, text) => {
  163. if (document.getElementById(id)) return;
  164. const style = document.createElement('style');
  165. style.id = id;
  166. style.textContent = text;
  167. document.head.appendChild(style);
  168.  
  169. }
  170.  
  171.  
  172. (async function () {
  173.  
  174. // Dynamically load CSS and JS
  175. await loadResource('css', `${vsPath}/editor/editor.main.css`);
  176. await loadResource('js', `${vsPath}/loader.js`);
  177. await loadResource('js', `${vsPath}/editor/editor.main.nls.js`);
  178. await loadResource('js', `${vsPath}/editor/editor.main.js`);
  179.  
  180. addCssText('rmbnctzOOksi', cssText01);
  181.  
  182. monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
  183. allowNonTsExtensions: true,
  184. checkJs: true,
  185. });
  186.  
  187. const container = document.createElement('div');
  188. container.className = 'monaco-editor-container';
  189. container.style.height = textArea.getBoundingClientRect().height + 'px';
  190. // textArea.replaceWith(container);
  191. textArea.classList.add('monaco-controlled-textarea');
  192. const textAreaParent = elmSet.textAreaParent = textArea.parentNode;
  193. textAreaParent.setAttribute('monaco-editor-status', '1');
  194. textAreaParent.insertBefore(container, textArea.nextSibling);
  195.  
  196. elmSet.textArea = textArea;
  197. elmSet.container = container;
  198.  
  199. const monacoLangs = {
  200. 'javascript': 'javascript',
  201. 'css': 'css',
  202. };
  203.  
  204. const monacoLang = monacoLangs[codeLang];
  205.  
  206.  
  207. const editor = monaco.editor.create(container, {
  208. value: textArea.value,
  209. language: monacoLang,
  210. automaticLayout: true,
  211. foldingStrategy: 'indentation',
  212. lineNumbers: 'on',
  213. readOnly: false,
  214. minimap: {
  215. enabled: false,
  216. },
  217. cursorStyle: 'line',
  218. });
  219.  
  220. elmSet.editor = editor;
  221.  
  222. if (document.documentElement.hasAttribute('dark')) monaco.editor.setTheme("vs-dark");
  223.  
  224. editor.onDidChangeModelContent(e => {
  225. elmSet.textArea.value = editor.getValue()
  226. });
  227.  
  228.  
  229. // console.log(monaco, monaco.onDidChangeModelContent)
  230.  
  231. // window.editor.getModel().onDidChangeContent((event) => {
  232. // render();
  233. // });
  234.  
  235. // editor.setTheme
  236.  
  237. // onDidChangeContent is attached to a model, and will only apply to that model
  238. // onDidChangeModelContent
  239.  
  240.  
  241.  
  242. })();
  243.  
  244.  
  245. }
  246.  
  247. function onReady() {
  248. window.removeEventListener("DOMContentLoaded", onReady, false);
  249.  
  250. if (localStorage.darkMode === 'true') document.documentElement.setAttribute('dark', '')
  251.  
  252. const checkerbox = document.querySelector('input#enable-source-editor-code[name="enable-source-editor-code"]');
  253.  
  254. if(checkerbox){
  255. checkerbox.addEventListener('change', onChange817, { once: false, capture: true, passive: false });
  256. if(localStorage.autoMonacoEditor === 'true' && requestIdleCallback){
  257. requestIdleCallback(()=>{
  258. if(checkerbox.checked === false && checkerbox.isConnected) checkerbox.click();
  259. });
  260.  
  261. }
  262. }
  263.  
  264.  
  265. }
  266.  
  267.  
  268. Promise.resolve().then(() => {
  269.  
  270. if (document.readyState !== 'loading') {
  271. onReady();
  272. } else {
  273. window.addEventListener("DOMContentLoaded", onReady, false);
  274. }
  275.  
  276. });
  277.  
  278. })();