var defaultUrl = localStorageGetItem("api-url") || "https://secure.judge0.com/standard"; var apiUrl = defaultUrl; var wait = localStorageGetItem("wait") || false; var pbUrl = "https://pb.judge0.com"; var check_timeout = 200; var blinkStatusLine = ((localStorageGetItem("blink") || "true") === "true"); var editorMode = localStorageGetItem("editorMode") || "normal"; var redirectStderrToStdout = ((localStorageGetItem("redirectStderrToStdout") || "false") === "true"); var editorModeObject = null; var fontSize = 14; var MonacoVim; var MonacoEmacs; var layout; var sourceEditor; var stdinEditor; var stdoutEditor; var stderrEditor; var compileOutputEditor; var sandboxMessageEditor; var isEditorDirty = false; var currentLanguageId; var $selectLanguage; var $compilerOptions; var $commandLineArguments; var $insertTemplateBtn; var $runBtn; var $navigationMessage; var $updates; var $statusLine; var timeStart; var timeEnd; var messagesData; var layoutConfig = { settings: { showPopoutIcon: false, reorderEnabled: true }, dimensions: { borderWidth: 3, headerHeight: 22 }, content: [{ type: "row", content: [{ type: "component", componentName: "source", title: "SOURCE", isClosable: false, componentState: { readOnly: false } }, { type: "column", content: [{ type: "stack", content: [{ type: "component", componentName: "stdin", title: "STDIN", isClosable: false, componentState: { readOnly: false } }] }, { type: "stack", content: [{ type: "component", componentName: "stdout", title: "STDOUT", isClosable: false, componentState: { readOnly: true } }, { type: "component", componentName: "stderr", title: "STDERR", isClosable: false, componentState: { readOnly: true } }, { type: "component", componentName: "compile output", title: "COMPILE OUTPUT", isClosable: false, componentState: { readOnly: true } }, { type: "component", componentName: "sandbox message", title: "SANDBOX MESSAGE", isClosable: false, componentState: { readOnly: true } }] }] }] }] }; function encode(str) { return btoa(unescape(encodeURIComponent(str || ""))); } function decode(bytes) { var escaped = escape(atob(bytes || "")); try { return decodeURIComponent(escaped); } catch { return unescape(escaped); } } function localStorageSetItem(key, value) { try { localStorage.setItem(key, value); } catch (ignorable) { } } function localStorageGetItem(key) { try { return localStorage.getItem(key); } catch (ignorable) { return null; } } function showMessages() { var width = $updates.offset().left - parseFloat($updates.css("padding-left")) - $navigationMessage.parent().offset().left - parseFloat($navigationMessage.parent().css("padding-left")) - 5; if (width < 200 || messagesData === undefined) { return; } var messages = messagesData["messages"]; $navigationMessage.css("animation-duration", messagesData["duration"]); $navigationMessage.parent().width(width - 5); var combinedMessage = ""; for (var i = 0; i < messages.length; ++i) { combinedMessage += `${messages[i]}`; if (i != messages.length - 1) { combinedMessage += " ".repeat(Math.min(200, messages[i].length)); } } $navigationMessage.html(combinedMessage); } function loadMessages() { $.ajax({ url: `https://minio.judge0.com/public/ide/messages.json?${Date.now()}`, type: "GET", headers: { "Accept": "application/json" }, success: function (data, textStatus, jqXHR) { messagesData = data; showMessages(); } }); } function showError(title, content) { $("#site-modal #title").html(title); $("#site-modal .content").html(content); $("#site-modal").modal("show"); } function handleError(jqXHR, textStatus, errorThrown) { showError(`${jqXHR.statusText} (${jqXHR.status})`, `
${JSON.stringify(jqXHR, null, 4)}`); } function handleRunError(jqXHR, textStatus, errorThrown) { handleError(jqXHR, textStatus, errorThrown); $runBtn.removeClass("loading"); } function handleResult(data) { timeEnd = performance.now(); console.log("It took " + (timeEnd - timeStart) + " ms to get submission result."); var status = data.status; var stdout = decode(data.stdout); var stderr = decode(data.stderr); var compile_output = decode(data.compile_output); var sandbox_message = decode(data.message); var time = (data.time === null ? "-" : data.time + "s"); var memory = (data.memory === null ? "-" : data.memory + "KB"); $statusLine.html(`${status.description}, ${time}, ${memory}`); if (blinkStatusLine) { $statusLine.addClass("blink"); setTimeout(function() { blinkStatusLine = false; localStorageSetItem("blink", "false"); $statusLine.removeClass("blink"); }, 3000); } stdoutEditor.setValue(stdout); stderrEditor.setValue(stderr); compileOutputEditor.setValue(compile_output); sandboxMessageEditor.setValue(sandbox_message); if (stdout !== "") { var dot = document.getElementById("stdout-dot"); if (!dot.parentElement.classList.contains("lm_active")) { dot.hidden = false; } } if (stderr !== "") { var dot = document.getElementById("stderr-dot"); if (!dot.parentElement.classList.contains("lm_active")) { dot.hidden = false; } } if (compile_output !== "") { var dot = document.getElementById("compile-output-dot"); if (!dot.parentElement.classList.contains("lm_active")) { dot.hidden = false; } } if (sandbox_message !== "") { var dot = document.getElementById("sandbox-message-dot"); if (!dot.parentElement.classList.contains("lm_active")) { dot.hidden = false; } } $runBtn.removeClass("loading"); } function getIdFromURI() { var uri = location.search.substr(1).trim(); return uri.split("&")[0]; } function save() { var content = JSON.stringify({ source_code: encode(sourceEditor.getValue()), language_id: $selectLanguage.val(), compiler_options: $compilerOptions.val(), command_line_arguments: $commandLineArguments.val(), stdin: encode(stdinEditor.getValue()), stdout: encode(stdoutEditor.getValue()), stderr: encode(stderrEditor.getValue()), compile_output: encode(compileOutputEditor.getValue()), sandbox_message: encode(sandboxMessageEditor.getValue()), status_line: encode($statusLine.html()) }); var filename = "judge0-ide.json"; var data = { content: content, filename: filename }; $.ajax({ url: pbUrl, type: "POST", async: true, headers: { "Accept": "application/json" }, data: data, xhrFields: { withCredentials: true }, success: function (data, textStatus, jqXHR) { if (getIdFromURI() != data["short"]) { window.history.replaceState(null, null, location.origin + location.pathname + "?" + data["short"]); } }, error: function (jqXHR, textStatus, errorThrown) { handleError(jqXHR, textStatus, errorThrown); } }); } function downloadSource() { var value = parseInt($selectLanguage.val()); download(sourceEditor.getValue(), fileNames[value], "text/plain"); } function loadSavedSource() { snippet_id = getIdFromURI(); if (snippet_id.length == 36) { $.ajax({ url: apiUrl + "/submissions/" + snippet_id + "?fields=source_code,language_id,stdin,stdout,stderr,compile_output,message,time,memory,status,compiler_options,command_line_arguments&base64_encoded=true", type: "GET", success: function(data, textStatus, jqXHR) { sourceEditor.setValue(decode(data["source_code"])); $selectLanguage.dropdown("set selected", data["language_id"]); $compilerOptions.val(data["compiler_options"]); $commandLineArguments.val(data["command_line_arguments"]); stdinEditor.setValue(decode(data["stdin"])); stdoutEditor.setValue(decode(data["stdout"])); stderrEditor.setValue(decode(data["stderr"])); compileOutputEditor.setValue(decode(data["compile_output"])); sandboxMessageEditor.setValue(decode(data["message"])); var time = (data.time === null ? "-" : data.time + "s"); var memory = (data.memory === null ? "-" : data.memory + "KB"); $statusLine.html(`${data.status.description}, ${time}, ${memory}`); changeEditorLanguage(); }, error: handleRunError }); } else if (snippet_id.length == 4) { $.ajax({ url: pbUrl + "/" + snippet_id + ".json", type: "GET", success: function (data, textStatus, jqXHR) { sourceEditor.setValue(decode(data["source_code"])); $selectLanguage.dropdown("set selected", data["language_id"]); $compilerOptions.val(data["compiler_options"]); $commandLineArguments.val(data["command_line_arguments"]); stdinEditor.setValue(decode(data["stdin"])); stdoutEditor.setValue(decode(data["stdout"])); stderrEditor.setValue(decode(data["stderr"])); compileOutputEditor.setValue(decode(data["compile_output"])); sandboxMessageEditor.setValue(decode(data["sandbox_message"])); $statusLine.html(decode(data["status_line"])); changeEditorLanguage(); }, error: function (jqXHR, textStatus, errorThrown) { showError("Not Found", "Code not found!"); window.history.replaceState(null, null, location.origin + location.pathname); loadRandomLanguage(); } }); } else { loadRandomLanguage(); } } function run() { if (sourceEditor.getValue().trim() === "") { showError("Error", "Source code can't be empty!"); return; } else { $runBtn.addClass("loading"); } document.getElementById("stdout-dot").hidden = true; document.getElementById("stderr-dot").hidden = true; document.getElementById("compile-output-dot").hidden = true; document.getElementById("sandbox-message-dot").hidden = true; stdoutEditor.setValue(""); stderrEditor.setValue(""); compileOutputEditor.setValue(""); sandboxMessageEditor.setValue(""); var sourceValue = encode(sourceEditor.getValue()); var stdinValue = encode(stdinEditor.getValue()); var languageId = resolveLanguageId($selectLanguage.val()); var compilerOptions = $compilerOptions.val(); var commandLineArguments = $commandLineArguments.val(); if (parseInt(languageId) === 44) { sourceValue = sourceEditor.getValue(); } var data = { source_code: sourceValue, language_id: languageId, stdin: stdinValue, compiler_options: compilerOptions, command_line_arguments: commandLineArguments, redirect_stderr_to_stdout: redirectStderrToStdout }; var sendRequest = function(data) { timeStart = performance.now(); $.ajax({ url: apiUrl + `/submissions?base64_encoded=true&wait=${wait}`, type: "POST", async: true, contentType: "application/json", data: JSON.stringify(data), xhrFields: { withCredentials: apiUrl.indexOf("/secure") != -1 ? true : false }, success: function (data, textStatus, jqXHR) { console.log(`Your submission token is: ${data.token}`); if (wait == true) { handleResult(data); } else { setTimeout(fetchSubmission.bind(null, data.token), check_timeout); } }, error: handleRunError }); } var fetchAdditionalFiles = false; if (parseInt(languageId) === 82) { if (sqliteAdditionalFiles === "") { fetchAdditionalFiles = true; $.ajax({ url: `https://minio.judge0.com/public/ide/sqliteAdditionalFiles.base64.txt?${Date.now()}`, type: "GET", async: true, contentType: "text/plain", success: function (responseData, textStatus, jqXHR) { sqliteAdditionalFiles = responseData; data["additional_files"] = sqliteAdditionalFiles; sendRequest(data); }, error: handleRunError }); } else { data["additional_files"] = sqliteAdditionalFiles; } } if (!fetchAdditionalFiles) { sendRequest(data); } } function fetchSubmission(submission_token) { $.ajax({ url: apiUrl + "/submissions/" + submission_token + "?base64_encoded=true", type: "GET", async: true, success: function (data, textStatus, jqXHR) { if (data.status.id <= 2) { // In Queue or Processing setTimeout(fetchSubmission.bind(null, submission_token), check_timeout); return; } handleResult(data); }, error: handleRunError }); } function changeEditorLanguage() { monaco.editor.setModelLanguage(sourceEditor.getModel(), $selectLanguage.find(":selected").attr("mode")); currentLanguageId = parseInt($selectLanguage.val()); $(".lm_title")[0].innerText = fileNames[currentLanguageId]; apiUrl = resolveApiUrl($selectLanguage.val()); } function insertTemplate() { currentLanguageId = parseInt($selectLanguage.val()); sourceEditor.setValue(sources[currentLanguageId]); changeEditorLanguage(); } function loadRandomLanguage() { var values = []; for (var i = 0; i < $selectLanguage[0].options.length; ++i) { values.push($selectLanguage[0].options[i].value); } $selectLanguage.dropdown("set selected", values[Math.floor(Math.random() * $selectLanguage[0].length)]); apiUrl = resolveApiUrl($selectLanguage.val()); insertTemplate(); } function resizeEditor(layoutInfo) { if (editorMode != "normal") { var statusLineHeight = $("#editor-status-line").height(); layoutInfo.height -= statusLineHeight; layoutInfo.contentHeight -= statusLineHeight; } } function disposeEditorModeObject() { try { editorModeObject.dispose(); editorModeObject = null; } catch(ignorable) { } } function changeEditorMode() { disposeEditorModeObject(); if (editorMode == "vim") { editorModeObject = MonacoVim.initVimMode(sourceEditor, $("#editor-status-line")[0]); } else if (editorMode == "emacs") { var statusNode = $("#editor-status-line")[0]; editorModeObject = new MonacoEmacs.EmacsExtension(sourceEditor); editorModeObject.onDidMarkChange(function(e) { statusNode.textContent = e ? "Mark Set!" : "Mark Unset"; }); editorModeObject.onDidChangeKey(function(str) { statusNode.textContent = str; }); editorModeObject.start(); } } function resolveLanguageId(id) { id = parseInt(id); return languageIdTable[id] || id; } function resolveApiUrl(id) { id = parseInt(id); return languageApiUrlTable[id] || defaultUrl; } function editorsUpdateFontSize(fontSize) { sourceEditor.updateOptions({fontSize: fontSize}); stdinEditor.updateOptions({fontSize: fontSize}); stdoutEditor.updateOptions({fontSize: fontSize}); stderrEditor.updateOptions({fontSize: fontSize}); compileOutputEditor.updateOptions({fontSize: fontSize}); sandboxMessageEditor.updateOptions({fontSize: fontSize}); } function updateScreenElements() { var display = window.innerWidth <= 1200 ? "none" : ""; $(".wide.screen.only").each(function(index) { $(this).css("display", display); }); } $(window).resize(function() { layout.updateSize(); updateScreenElements(); showMessages(); }); $(document).ready(function () { updateScreenElements(); console.log("Hey, Judge0 IDE is open-sourced: https://github.com/judge0/ide. Have fun!"); $selectLanguage = $("#select-language"); $selectLanguage.change(function (e) { if (!isEditorDirty) { insertTemplate(); } else { changeEditorLanguage(); } }); $compilerOptions = $("#compiler-options"); $commandLineArguments = $("#command-line-arguments"); $commandLineArguments.attr("size", $commandLineArguments.attr("placeholder").length); $insertTemplateBtn = $("#insert-template-btn"); $insertTemplateBtn.click(function (e) { if (isEditorDirty && confirm("Are you sure? Your current changes will be lost.")) { insertTemplate(); } }); $runBtn = $("#run-btn"); $runBtn.click(function (e) { run(); }); $navigationMessage = $("#navigation-message span"); $updates = $("#updates"); $(`input[name="editor-mode"][value="${editorMode}"]`).prop("checked", true); $("input[name=\"editor-mode\"]").on("change", function(e) { editorMode = e.target.value; localStorageSetItem("editorMode", editorMode); resizeEditor(sourceEditor.getLayoutInfo()); changeEditorMode(); sourceEditor.focus(); }); $("input[name=\"redirect-output\"]").prop("checked", redirectStderrToStdout) $("input[name=\"redirect-output\"]").on("change", function(e) { redirectStderrToStdout = e.target.checked; localStorageSetItem("redirectStderrToStdout", redirectStderrToStdout); }); $statusLine = $("#status-line"); $("body").keydown(function (e) { var keyCode = e.keyCode || e.which; if (keyCode == 120) { // F9 e.preventDefault(); run(); } else if (keyCode == 119) { // F8 e.preventDefault(); var url = prompt("Enter URL of Judge0 API:", apiUrl); if (url != null) { url = url.trim(); } if (url != null && url != "") { apiUrl = url; localStorageSetItem("api-url", apiUrl); } } else if (keyCode == 118) { // F7 e.preventDefault(); wait = !wait; localStorageSetItem("wait", wait); alert(`Submission wait is ${wait ? "ON. Enjoy" : "OFF"}.`); } else if (event.ctrlKey && keyCode == 83) { // Ctrl+S e.preventDefault(); save(); } else if (event.ctrlKey && keyCode == 107) { // Ctrl++ e.preventDefault(); fontSize += 1; editorsUpdateFontSize(fontSize); } else if (event.ctrlKey && keyCode == 109) { // Ctrl+- e.preventDefault(); fontSize -= 1; editorsUpdateFontSize(fontSize); } }); $("select.dropdown").dropdown(); $(".ui.dropdown").dropdown(); $(".ui.dropdown.site-links").dropdown({action: "hide", on: "hover"}); $(".ui.checkbox").checkbox(); $(".message .close").on("click", function () { $(this).closest(".message").transition("fade"); }); loadMessages(); require(["vs/editor/editor.main", "monaco-vim", "monaco-emacs"], function (ignorable, MVim, MEmacs) { layout = new GoldenLayout(layoutConfig, $("#site-content")); MonacoVim = MVim; MonacoEmacs = MEmacs; layout.registerComponent("source", function (container, state) { sourceEditor = monaco.editor.create(container.getElement()[0], { automaticLayout: true, theme: "vs-dark", scrollBeyondLastLine: true, readOnly: state.readOnly, language: "cpp", minimap: { enabled: false }, rulers: [80, 120] }); changeEditorMode(); sourceEditor.getModel().onDidChangeContent(function (e) { currentLanguageId = parseInt($selectLanguage.val()); isEditorDirty = sourceEditor.getValue() != sources[currentLanguageId]; }); sourceEditor.onDidLayoutChange(resizeEditor); }); layout.registerComponent("stdin", function (container, state) { stdinEditor = monaco.editor.create(container.getElement()[0], { automaticLayout: true, theme: "vs-dark", scrollBeyondLastLine: false, readOnly: state.readOnly, language: "plaintext", minimap: { enabled: false } }); }); layout.registerComponent("stdout", function (container, state) { stdoutEditor = monaco.editor.create(container.getElement()[0], { automaticLayout: true, theme: "vs-dark", scrollBeyondLastLine: false, readOnly: state.readOnly, language: "plaintext", minimap: { enabled: false } }); container.on("tab", function(tab) { tab.element.append(""); tab.element.on("mousedown", function(e) { e.target.closest(".lm_tab").children[3].hidden = true; }); }); }); layout.registerComponent("stderr", function (container, state) { stderrEditor = monaco.editor.create(container.getElement()[0], { automaticLayout: true, theme: "vs-dark", scrollBeyondLastLine: false, readOnly: state.readOnly, language: "plaintext", minimap: { enabled: false } }); container.on("tab", function(tab) { tab.element.append(""); tab.element.on("mousedown", function(e) { e.target.closest(".lm_tab").children[3].hidden = true; }); }); }); layout.registerComponent("compile output", function (container, state) { compileOutputEditor = monaco.editor.create(container.getElement()[0], { automaticLayout: true, theme: "vs-dark", scrollBeyondLastLine: false, readOnly: state.readOnly, language: "plaintext", minimap: { enabled: false } }); container.on("tab", function(tab) { tab.element.append(""); tab.element.on("mousedown", function(e) { e.target.closest(".lm_tab").children[3].hidden = true; }); }); }); layout.registerComponent("sandbox message", function (container, state) { sandboxMessageEditor = monaco.editor.create(container.getElement()[0], { automaticLayout: true, theme: "vs-dark", scrollBeyondLastLine: false, readOnly: state.readOnly, language: "plaintext", minimap: { enabled: false } }); container.on("tab", function(tab) { tab.element.append(""); tab.element.on("mousedown", function(e) { e.target.closest(".lm_tab").children[3].hidden = true; }); }); }); layout.on("initialised", function () { $(".monaco-editor")[0].appendChild($("#editor-status-line")[0]); if (getIdFromURI()) { loadSavedSource(); } else { loadRandomLanguage(); } $("#site-navigation").css("border-bottom", "1px solid black"); sourceEditor.focus(); }); layout.init(); }); }); // Template Sources var assemblySource = "\ section .text\n\ global _start\n\ \n\ _start:\n\ \n\ xor eax, eax\n\ lea edx, [rax+len]\n\ mov al, 1\n\ mov esi, msg\n\ mov edi, eax\n\ syscall\n\ \n\ xor edi, edi\n\ lea eax, [rdi+60]\n\ syscall\n\ \n\ section .rodata\n\ \n\ msg db 'hello, world', 0xa\n\ len equ $ - msg\n\ "; var bashSource = "echo \"hello, world\""; var basicSource = "PRINT \"hello, world\""; var cSource = "\ #include