// ==UserScript==
// @name GreasyFork Code: Monaco Editor
// @namespace Violentmonkey Scripts
// @match https://greasyfork.org/*
// @match https://sleazyfork.org/*
// @grant none
// @version 0.1.12
// @author CY Fung
// @description 12/17/2023, 2:31:22 PM
// @run-at document-start
// @unwrap
// @license MIT
// ==/UserScript==
// localStorage.darkMode = 'true'
// localStorage.autoMonacoEditor = 'true'
(() => {
const vsPath = "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.45.0/min/vs";
const editorOptions = {
automaticLayout: true,
foldingStrategy: 'indentation',
lineNumbers: 'on',
readOnly: false,
minimap: {
enabled: false,
},
cursorStyle: 'line',
scrollBeyondLastLine: false,
showUnused: true,
showDeprecated: true,
};
const compilerOptions = {
allowNonTsExtensions: true,
checkJs: true,
noImplicitAny: true,
allowJs: true,
noUnusedLocals: false,
noFallthroughCasesInSwitch: false,
noImplicitThis: false,
};
const cssText01 = `
.monaco-editor-container{
margin: 0;
padding: 0;
box-sizing: border-box;
display: none;
}
[monaco-editor-status="1"] .monaco-editor-container{
display: block;
}
[monaco-editor-status="1"] .monaco-controlled-textarea{
display: none;
}
[monaco-editor-status="2"] .monaco-editor-container{
display: none;
}
[monaco-editor-status="2"] .monaco-controlled-textarea{
display: block;
}
`;
const elmSet = {};
HTMLInputElement.prototype.addEventListener177 = HTMLInputElement.prototype.addEventListener;
HTMLInputElement.prototype.addEventListener = function () {
if (arguments.length === 2 && arguments[0] === 'change' && (arguments[1] || 0).name === 'handleChange') {
const rawF = arguments[1];
if (this.id === 'enable-source-editor-code') {
arguments[1] = function handleChange(e) {
if (typeof ((e || 0).target || 0).checked === 'boolean' && document.getElementById('ace-editor')) return rawF.apply(this, arguments);
}
}
}
return this.addEventListener177.apply(this, arguments);
}
function loadResource(type, url) {
if (type === 'css') {
return new Promise(resolve => {
var link = document.createElement('link');
var onload = function () {
link.removeEventListener('load', onload, false);
resolve();
}
link.addEventListener('load', onload, false);
link.rel = 'stylesheet';
link.href = url;
document.head.appendChild(link);
});
} else if (type === 'js') {
return new Promise(resolve => {
var script = document.createElement('script');
var onload = function () {
script.removeEventListener('load', onload, false);
resolve();
}
script.addEventListener('load', onload, false);
script.src = url;
document.head.appendChild(script);
})
}
}
function onChange817(e) {
const target = (e || 0).target || null;
if (!target) return;
let monacoStatus = target.getAttribute('monaco-status')
if (monacoStatus) {
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
const textAreaParent = elmSet.textAreaParent;
const textArea = elmSet.textArea;
const editor = elmSet.editor;
// console.log(monacoStatus)
if (monacoStatus === '1') {
// elmSet.container.replaceWith(elmSet.textArea);
textAreaParent.setAttribute('monaco-editor-status', '2')
target.setAttribute('monaco-status', monacoStatus = '2')
if (textArea.style.display) textArea.style.display = '';
return;
} else if (monacoStatus === '2') {
// elmSet.textArea.replaceWith(elmSet.container);
const currentCode = editor.getValue();
const currentText = textArea.value;
if (currentCode !== currentText) {
editor.setValue(currentText);
}
textAreaParent.setAttribute('monaco-editor-status', '1')
target.setAttribute('monaco-status', monacoStatus = '1')
if (textArea.style.display) textArea.style.display = '';
return;
} else {
return;
}
}
const codeId = target.getAttribute('data-related-editor') || '';
if (!codeId) return;
const textArea = document.getElementById(codeId);
if (!textArea) return;
const codeLang = target.getAttribute('data-editor-language'); // 'javascript', 'css'
if (!codeLang) return;
if (document.getElementById('ace-editor')) return;
target.setAttribute('monaco-status', '1');
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
// Setting up Monaco Editor requirements
let require = {
paths: {
vs: vsPath,
},
};
window.require = (window.require || {});
window.require.paths = (window.require.paths || {});
Object.assign(window.require.paths, require.paths);
const addCssText = (id, text) => {
if (document.getElementById(id)) return;
const style = document.createElement('style');
style.id = id;
style.textContent = text;
document.head.appendChild(style);
}
(async function () {
// Dynamically load CSS and JS
await loadResource('css', `${vsPath}/editor/editor.main.css`);
await loadResource('js', `${vsPath}/loader.js`);
await loadResource('js', `${vsPath}/editor/editor.main.nls.js`);
await loadResource('js', `${vsPath}/editor/editor.main.js`);
addCssText('rmbnctzOOksi', cssText01);
monaco.languages.typescript.javascriptDefaults.setCompilerOptions(Object.assign({
target: monaco.languages.typescript.ScriptTarget.ES2018,
}, compilerOptions));
const container = document.createElement('div');
container.className = 'monaco-editor-container';
container.style.height = textArea.getBoundingClientRect().height + 'px';
// textArea.replaceWith(container);
textArea.classList.add('monaco-controlled-textarea');
const textAreaParent = elmSet.textAreaParent = textArea.parentNode;
textAreaParent.setAttribute('monaco-editor-status', '1');
textAreaParent.insertBefore(container, textArea.nextSibling);
elmSet.textArea = textArea;
elmSet.container = container;
if (textArea.style.display) textArea.style.display = '';
const monacoLangs = {
'javascript': 'javascript',
'css': 'css',
};
const monacoLang = monacoLangs[codeLang];
const editor = monaco.editor.create(container, Object.assign({
value: textArea.value,
language: monacoLang
}, editorOptions));
elmSet.editor = editor;
if (document.documentElement.hasAttribute('dark')) monaco.editor.setTheme("vs-dark");
editor.onDidChangeModelContent(e => {
elmSet.textArea.value = editor.getValue()
});
// console.log(monaco, monaco.onDidChangeModelContent)
// window.editor.getModel().onDidChangeContent((event) => {
// render();
// });
// editor.setTheme
// onDidChangeContent is attached to a model, and will only apply to that model
// onDidChangeModelContent
})();
}
function preloadResources() {
const cssResources = [
`${vsPath}/editor/editor.main.css`,
];
const jsResources = [
`${vsPath}/loader.js`,
`${vsPath}/editor/editor.main.nls.js`,
`${vsPath}/editor/editor.main.js`,
];
const template = document.createElement('template');
const frag = template.content;
for (const url of cssResources) {
const link = document.createElement('link');
link.setAttribute('rel', 'preload');
link.setAttribute('as', 'style');
link.setAttribute('href', url);
frag.appendChild(link);
}
for (const url of jsResources) {
const link = document.createElement('link');
link.setAttribute('rel', 'preload');
link.setAttribute('as', 'script');
link.setAttribute('href', url);
frag.appendChild(link);
}
document.head.appendChild(frag);
}
function onReady() {
window.removeEventListener("DOMContentLoaded", onReady, false);
if (location.pathname.includes('/script')) {
preloadResources();
}
// if (localStorage.darkMode === 'true') document.documentElement.setAttribute('dark', '')
const checkerbox = document.querySelector('input#enable-source-editor-code[name="enable-source-editor-code"]');
if (checkerbox) {
checkerbox.addEventListener('change', onChange817, { once: false, capture: true, passive: false });
if (localStorage.autoMonacoEditor === 'true' && requestIdleCallback) {
requestIdleCallback(() => {
if (checkerbox.checked === false && checkerbox.isConnected) checkerbox.click();
else if (checkerbox.checked === true && document.getElementById('ace-editor') && checkerbox.isConnected) {
Promise.resolve().then(() => checkerbox.click()).then(() => checkerbox.click())
}
});
}
}
}
Promise.resolve().then(() => {
if (document.readyState !== 'loading') {
onReady();
} else {
window.addEventListener("DOMContentLoaded", onReady, false);
}
});
})();