GreasyFork Code: Monaco Editor

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

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

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址