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://gf.qytechs.cn/*
  5. // @match https://sleazyfork.org/*
  6. // @grant none
  7. // @version 0.1.8
  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. if (this.id === 'enable-source-editor-code') return;
  75. }
  76. return this.addEventListener177.apply(this, arguments);
  77. }
  78.  
  79. function loadResource(type, url) {
  80. if (type === 'css') {
  81. return new Promise(resolve => {
  82. var link = document.createElement('link');
  83. var onload = function () {
  84. link.removeEventListener('load', onload, false);
  85. resolve();
  86. }
  87. link.addEventListener('load', onload, false);
  88. link.rel = 'stylesheet';
  89. link.href = url;
  90. document.head.appendChild(link);
  91. });
  92. } else if (type === 'js') {
  93. return new Promise(resolve => {
  94. var script = document.createElement('script');
  95. var onload = function () {
  96. script.removeEventListener('load', onload, false);
  97. resolve();
  98. }
  99. script.addEventListener('load', onload, false);
  100. script.src = url;
  101. document.head.appendChild(script);
  102. })
  103. }
  104. }
  105.  
  106. function onChange817(e) {
  107.  
  108.  
  109.  
  110. // console.log(123213)
  111.  
  112. const target = (e || 0).target || null;
  113.  
  114. if (!target) return;
  115.  
  116. let monacoStatus = target.getAttribute('monaco-status')
  117. if (monacoStatus) {
  118.  
  119. e.stopImmediatePropagation();
  120. e.stopPropagation();
  121. e.preventDefault();
  122.  
  123. const textAreaParent = elmSet.textAreaParent;
  124. const textArea = elmSet.textArea;
  125. const editor = elmSet.editor;
  126.  
  127. // console.log(monacoStatus)
  128. if (monacoStatus === '1') {
  129. // elmSet.container.replaceWith(elmSet.textArea);
  130.  
  131.  
  132.  
  133. textAreaParent.setAttribute('monaco-editor-status', '2')
  134. target.setAttribute('monaco-status', monacoStatus = '2')
  135. return;
  136.  
  137. } else if (monacoStatus === '2') {
  138.  
  139. // elmSet.textArea.replaceWith(elmSet.container);
  140.  
  141. const currentCode = editor.getValue();
  142. const currentText = textArea.value;
  143. if (currentCode !== currentText) {
  144. editor.setValue(currentText);
  145. }
  146.  
  147. textAreaParent.setAttribute('monaco-editor-status', '1')
  148. target.setAttribute('monaco-status', monacoStatus = '1')
  149. return;
  150. } else {
  151. return;
  152. }
  153.  
  154. }
  155.  
  156. const codeId = target.getAttribute('data-related-editor') || '';
  157. if (!codeId) return;
  158.  
  159. const textArea = document.getElementById(codeId);
  160.  
  161. if (!textArea) return;
  162.  
  163. const codeLang = target.getAttribute('data-editor-language'); // 'javascript', 'css'
  164.  
  165. if (!codeLang) return;
  166.  
  167.  
  168. target.setAttribute('monaco-status', '1');
  169.  
  170.  
  171. e.stopImmediatePropagation();
  172. e.stopPropagation();
  173. e.preventDefault();
  174.  
  175.  
  176. // Setting up Monaco Editor requirements
  177. let require = {
  178. paths: {
  179. vs: vsPath,
  180. },
  181. };
  182.  
  183. window.require = (window.require || {});
  184. window.require.paths = (window.require.paths || {});
  185. Object.assign(window.require.paths, require.paths);
  186.  
  187.  
  188. const addCssText = (id, text) => {
  189. if (document.getElementById(id)) return;
  190. const style = document.createElement('style');
  191. style.id = id;
  192. style.textContent = text;
  193. document.head.appendChild(style);
  194.  
  195. }
  196.  
  197.  
  198. (async function () {
  199.  
  200. // Dynamically load CSS and JS
  201. await loadResource('css', `${vsPath}/editor/editor.main.css`);
  202. await loadResource('js', `${vsPath}/loader.js`);
  203. await loadResource('js', `${vsPath}/editor/editor.main.nls.js`);
  204. await loadResource('js', `${vsPath}/editor/editor.main.js`);
  205.  
  206. addCssText('rmbnctzOOksi', cssText01);
  207.  
  208. monaco.languages.typescript.javascriptDefaults.setCompilerOptions(Object.assign({
  209. target: monaco.languages.typescript.ScriptTarget.ES2018,
  210. }, compilerOptions));
  211.  
  212. const container = document.createElement('div');
  213. container.className = 'monaco-editor-container';
  214. container.style.height = textArea.getBoundingClientRect().height + 'px';
  215. // textArea.replaceWith(container);
  216. textArea.classList.add('monaco-controlled-textarea');
  217. const textAreaParent = elmSet.textAreaParent = textArea.parentNode;
  218. textAreaParent.setAttribute('monaco-editor-status', '1');
  219. textAreaParent.insertBefore(container, textArea.nextSibling);
  220.  
  221. elmSet.textArea = textArea;
  222. elmSet.container = container;
  223.  
  224. const monacoLangs = {
  225. 'javascript': 'javascript',
  226. 'css': 'css',
  227. };
  228.  
  229. const monacoLang = monacoLangs[codeLang];
  230.  
  231.  
  232. const editor = monaco.editor.create(container, Object.assign({
  233. value: textArea.value,
  234. language: monacoLang
  235. }, editorOptions));
  236.  
  237. elmSet.editor = editor;
  238.  
  239. if (document.documentElement.hasAttribute('dark')) monaco.editor.setTheme("vs-dark");
  240.  
  241. editor.onDidChangeModelContent(e => {
  242. elmSet.textArea.value = editor.getValue()
  243. });
  244.  
  245.  
  246. // console.log(monaco, monaco.onDidChangeModelContent)
  247.  
  248. // window.editor.getModel().onDidChangeContent((event) => {
  249. // render();
  250. // });
  251.  
  252. // editor.setTheme
  253.  
  254. // onDidChangeContent is attached to a model, and will only apply to that model
  255. // onDidChangeModelContent
  256.  
  257.  
  258.  
  259. })();
  260.  
  261.  
  262. }
  263.  
  264. function preloadResources() {
  265.  
  266. const cssResources = [
  267. `${vsPath}/editor/editor.main.css`,
  268. ];
  269. const jsResources = [
  270. `${vsPath}/loader.js`,
  271. `${vsPath}/editor/editor.main.nls.js`,
  272. `${vsPath}/editor/editor.main.js`,
  273. ];
  274. const template = document.createElement('template');
  275. const frag = template.content;
  276.  
  277. for (const url of cssResources) {
  278. const link = document.createElement('link');
  279. link.setAttribute('rel', 'preload');
  280. link.setAttribute('as', 'style');
  281. link.setAttribute('href', url);
  282. frag.appendChild(link);
  283. }
  284. for (const url of jsResources) {
  285. const link = document.createElement('link');
  286. link.setAttribute('rel', 'preload');
  287. link.setAttribute('as', 'script');
  288. link.setAttribute('href', url);
  289. frag.appendChild(link);
  290. }
  291. document.head.appendChild(frag);
  292. }
  293.  
  294.  
  295.  
  296. function onReady() {
  297. window.removeEventListener("DOMContentLoaded", onReady, false);
  298.  
  299. if (location.pathname.includes('/script')) {
  300. preloadResources();
  301. }
  302.  
  303. if (localStorage.darkMode === 'true') document.documentElement.setAttribute('dark', '')
  304.  
  305. const checkerbox = document.querySelector('input#enable-source-editor-code[name="enable-source-editor-code"]');
  306.  
  307. if (checkerbox) {
  308. checkerbox.addEventListener('change', onChange817, { once: false, capture: true, passive: false });
  309. if (localStorage.autoMonacoEditor === 'true' && requestIdleCallback) {
  310.  
  311. requestIdleCallback(() => {
  312. if (checkerbox.checked === false && checkerbox.isConnected) checkerbox.click();
  313. });
  314.  
  315. }
  316. }
  317.  
  318.  
  319.  
  320. }
  321.  
  322.  
  323. Promise.resolve().then(() => {
  324.  
  325. if (document.readyState !== 'loading') {
  326. onReady();
  327. } else {
  328. window.addEventListener("DOMContentLoaded", onReady, false);
  329. }
  330.  
  331. });
  332.  
  333. })();

QingJ © 2025

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