Runestone Monaco

Makes Runestone use the Monaco Editor.

// ==UserScript==
// @name         Runestone Monaco
// @namespace    https://balt.sno.mba
// @version      1.0
// @description  Makes Runestone use the Monaco Editor.
// @author       Heptor44
// @match        https://runestone.academy/*
// @run-at       document-start
// @grant        none
// @license      MIT
// ==/UserScript==

var _bind = Function.prototype.apply.bind(Function.prototype.bind);
Object.defineProperty(Function.prototype, 'bind', {
    value: function(obj) {
        var boundFunction = _bind(this, arguments);
        boundFunction.boundObject = obj;
        return boundFunction;
    }
});
window.addEventListener('load', function() {
    let script = document.createElement("script");
    script.onload = function () {
        document.querySelectorAll(".CodeMirror").forEach(parent => {
            let language = parent.parentNode.parentNode.lang;
            let runButton = parent.parentElement.parentElement.querySelector(".ac_actions").querySelector(".btn");
            let boxReference = runButton.onclick.boundObject;
            let program = boxReference.editor.getValue();
            parent.innerHTML = "";
            parent.style.overflow = "auto";
            parent.style.resize = "vertical";
            require.config({ paths: { 'vs': 'https://unpkg.com/monaco-editor@latest/min/vs' }});
            window.MonacoEnvironment = { getWorkerUrl: () => proxy };

            let proxy = URL.createObjectURL(new Blob([`self.MonacoEnvironment={baseUrl:"https://unpkg.com/monaco-editor@latest/min/"},importScripts("https://unpkg.com/monaco-editor@latest/min/vs/base/worker/workerMain.js");`], { type: 'text/javascript' }));

            require(["vs/editor/editor.main"], function () {
                var editor = monaco.editor.create(parent, {
                    value: program,
                    language: language,
                    theme: 'vs-' + document.documentElement.getAttribute("data-theme"),
                    automaticLayout: true
                });
                boxReference.editor = editor;
            });
        });
    };
    script.src = "https://unpkg.com/monaco-editor@latest/min/vs/loader.js";
    document.head.appendChild(script);
}, false);