您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
AtCoderのエディタをMonacoに差し替えます
// ==UserScript== // @name Ace to Monaco for AtCoder // @namespace https://yahoo.co.jp // @version 1.0.0 // @description AtCoderのエディタをMonacoに差し替えます // @author 茶色コーダー // @license MIT // @match https://atcoder.jp/contests/*/custom_test // @exclude // @grant none // ==/UserScript== // 要素が出現するまで待つ関数(出てこなかったら永遠ループ) const waitQuerySelector = async function (selector, node = document) { let obj = null; while (!obj) { obj = await new Promise((resolve) => setTimeout(() => resolve(node.querySelector(selector), 100)) ); } return obj; }; // 指定秒数待つ関数 const wait = async (ms) => new Promise((resolve) => setTimeout(resolve, ms)); const func1 = async function () { // headを取得する const head = document.head; // headの末尾にMonaco Editor用CSS(+α)を追加する head.insertAdjacentHTML( "beforeEnd", `<link rel="stylesheet" data-name="vs/editor/editor.main" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.45.0/min/vs/editor/editor.main.min.css" /> <style>#editor {max-height: 600px;}</style>` ); const script = document.createElement("script"); script.src = "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.45.0/min/vs/loader.min.js"; document.head.prepend(script); // ACEエディタの中身はいらないので消す const editor = document.getElementById("editor"); editor.innerHTML = ""; // loaderを読み込み終わったら処理開始 script.onload = async function () { // 画面読み込み時の初期コードの取得 const initCode = document.querySelector("#plain-textarea").innerText; // プログラミング言語を選択する要素の取得(読み込み対策で0.1秒遅延) await wait(100); const langSelector = document.querySelector('select[name="data.LanguageId"]'); const langOptions = Array.from(document.querySelectorAll("option")); // 選択した要素のIDがどの言語なのか判別 const langText = langOptions.find((item) => { return item.getAttribute("value") === langSelector.value; }); const langMode = langText ? langText.getAttribute("data-ace-mode") : "text"; // console.log("最初のテキストは", langMode); // Monaco EditorのCDNのパスを設定 require.config({ paths: { vs: "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.45.0/min/vs" }, }); // Monaco Editor周りの処理 require(["vs/editor/editor.main"], async function () { // Monaco Editorを降臨させる const localEditor = monaco.editor.create(editor, { value: initCode, language: langMode, theme: "vs-dark", lineHeight: 21, }); // 言語変更時の監視対象のエレメントの取得 const langElement = await waitQuerySelector(".select2-selection__rendered"); //MutationObserver(インスタンス)の作成 var mo = new MutationObserver(function (record, observer) { const lang = langOptions.find((item) => { return item.getAttribute("value") === langSelector.value; }); // console.info( // "innerText: ", // langElement.innerText, // "\n ace-mode: ", // lang.getAttribute("data-ace-mode") // ); // Editorに新たな言語を設定 monaco.editor.setModelLanguage( localEditor.getModel(), lang.getAttribute("data-ace-mode") ); }); // 監視する「もの」の指定(必ず1つ以上trueにする) var config = { childList: true, //「子ノード(テキストノードも含む)」の変化 attributes: false, //「属性」の変化 characterData: false, //「テキストノード」の変化 }; // 監視の開始 mo.observe(langElement, config); // コードテストのform実行時にAce Editorから値を持ってきてしまうので、 // その上からMonaco Editorの値で書き換える const formRef = $(".form-code-submit"); formRef.on("submit", function () { $("#plain-textarea").val(localEditor.getValue()); }); }); }; }; async function execWorkflow() { await func1(); } // メイン処理の実行タイミングが、windowのロード時となるように登録する window.addEventListener("load", async function () { await execWorkflow(); });