Skip to content

Use Monaco Editor and save code in submitpage.php when edit the content.#989

Open
def-WA2025 wants to merge 3 commits into
devfrom
def-WA2025/monaco-editor-and-save-code
Open

Use Monaco Editor and save code in submitpage.php when edit the content.#989
def-WA2025 wants to merge 3 commits into
devfrom
def-WA2025/monaco-editor-and-save-code

Conversation

@def-WA2025
Copy link
Copy Markdown
Member

@def-WA2025 def-WA2025 commented May 30, 2026

What does this PR aim to accomplish?:

Use Monaco Editor and save code in submitpage.php when edit the content.

How does this PR accomplish the above?:

Editor -> Monaco

Save code in localStorage.


By submitting this pull request, I confirm the following:

  1. I have read and understood the contributor's guide, as well as this entire template. I understand which branch to base my commits and Pull Requests against.
  2. I have commented on my proposed changes within the code.
  3. I have tested my changes.
  4. I am willing to help maintain this change if there are issues with it later.
  5. It is compatible with the GNU General Public License v3.0
  6. I have squashed any insignificant commits. (git rebase)
  7. I have checked that another pull request for this purpose does not exist.
  8. I have considered and confirmed that this submission will be valuable to others.
  9. I accept that this submission may not be used, and the pull request can be closed at the will of the maintainer.
  10. I give this submission freely and claim no ownership to its content.
  11. I have verified that my changes work correctly in both the new UI and the old/classic UI.

  • I have read the above and my PR is ready for review. Check this box to confirm

Summary by Sourcery

Switch the submit page code editor to Monaco and integrate it with existing scripting utilities while preserving compatibility via a CodeMirror shim.

New Features:

  • Add a Monaco-based code editor for the submit page, including keyboard shortcuts for submit and autocomplete, with per-problem code persisted in localStorage.

Enhancements:

  • Introduce a generic Monaco loader and helper utilities, including a CodeMirror-compatible shim and diff view wrapper for broader editor integration.
  • Apply custom Monaco styling and use a compact read-only Monaco instance (or fallback text) to display generated freopen snippets in error messages.

Summary by cubic

Replaced the submit page editor with monaco-editor and added automatic local save/restore of code. This improves the editing experience and helps prevent code loss on refresh.

  • New Features

    • Load monaco-editor from CDN and add a small shim to keep existing CodeMirror calls working.
    • Save code to localStorage per problem/contest and restore it on load.
    • Shortcuts: Ctrl/Cmd+Enter to submit, Ctrl/Cmd+Space for suggestions.
    • Respect dark mode, enable automatic layout, disable minimap by default.
    • Use a read-only Monaco block for the freopen snippet in error messages, with a <pre> fallback.
  • Dependencies

    • Bump xmoj-script to 3.5.2 and add a prerelease entry in Update.json.

Written for commit 6f7cc75. Summary will update on new commits.

Review in cubic

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented May 30, 2026

Reviewer's Guide

Replaces the existing CodeMirror-based editor integration with a Monaco-based implementation, including a dynamic loader/shim and localStorage-backed persistence for submitpage.php, and adjusts related code display snippets to use Monaco or a simple fallback where appropriate.

Sequence diagram for Monaco editor initialization and autosave on submitpage.php

sequenceDiagram
    actor User
    participant SubmitPage
    participant ensureMonaco
    participant createMonacoEditor
    participant MonacoEditor
    participant localStorage

    User->>SubmitPage: Open /submitpage.php
    SubmitPage->>createMonacoEditor: createMonacoEditor('MonacoEditor', options)
    createMonacoEditor->>ensureMonaco: ensureMonaco()
    ensureMonaco->>ensureMonaco: Load loader.js via script
    ensureMonaco->>ensureMonaco: require(['vs/editor/editor.main'])
    ensureMonaco-->>createMonacoEditor: monaco ready
    createMonacoEditor->>MonacoEditor: monaco.editor.create(container, config)
    createMonacoEditor->>localStorage: getItem(localStorageKey)
    localStorage-->>createMonacoEditor: saved code (if any)
    createMonacoEditor->>MonacoEditor: editor.setValue(saved)
    createMonacoEditor-->>SubmitPage: adapter (CodeMirrorElement)

    User->>MonacoEditor: Edit code
    MonacoEditor-->>localStorage: setItem(localStorageKey, value) (debounced)

    User->>MonacoEditor: Press Ctrl+Enter
    MonacoEditor->>SubmitPage: Submit.click()
Loading

File-Level Changes

Change Details Files
Introduce a reusable Monaco editor loader, factory, and CodeMirror-compatible shim to integrate Monaco across the script.
  • Add ensureMonaco helper to dynamically load Monaco from jsDelivr, configure AMD loader paths, and inject custom styling for rounded editor UI elements.
  • Implement createMonacoEditor to create and configure a Monaco editor instance with theme selection, language detection, autosizing, debounced localStorage persistence, and a thin adapter interface.
  • Provide a global CodeMirror shim that wraps textareas or containers, asynchronously upgrades them to Monaco editors, and supplies basic MergeView/diff functionality using Monaco's diff editor.
XMOJ.user.js
Swap the submitpage.php code textarea editor to Monaco and persist code drafts per-problem or per-contest in localStorage.
  • Replace the visible CodeMirror textarea with a div host for Monaco and hide the original textarea while preserving the surrounding submit UI.
  • Instantiate a Monaco editor on the submit page using createMonacoEditor with C++ language settings, dark/light theme based on UtilityEnabled, automatic layout, and a per-problem/per-contest localStorage key for draft persistence.
  • Bind Monaco keyboard commands so Ctrl+Enter triggers form submission and Ctrl+Space triggers code completion, and size the editor to a fixed 400px height with appropriate border styling.
XMOJ.user.js
Update the "freopen" snippet in the error message area to use Monaco for read-only display when available, with a plain
 fallback otherwise.
  • Replace the previous CodeMirror instantiation for the freopen helper snippet with creation of a dedicated div host appended to the ErrorMessage container.
  • When Monaco is present, create a small read-only Monaco editor configured for C++ with dark/light theme, no minimap, automatic layout, and line numbers for the snippet.
  • If Monaco is not available, fall back to appending a preformatted text element containing the freopen code, ensuring the snippet still displays correctly.
XMOJ.user.js

Possibly linked issues

  • #N/A: PR implements Monaco editor on submit page and localStorage saving, exactly matching the feature request.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@hendragon-bot hendragon-bot Bot added the user-script This issue or pull request is related to the main user script label May 30, 2026
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 30, 2026

Deploying xmoj-script-dev-channel with  Cloudflare Pages  Cloudflare Pages

Latest commit: 6f7cc75
Status: ✅  Deploy successful!
Preview URL: https://75217859.xmoj-script-dev-channel.pages.dev
Branch Preview URL: https://def-wa2025-monaco-editor-and.xmoj-script-dev-channel.pages.dev

View logs

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 security issues, 1 other issue, and left some high level feedback:

Security issues:

  • User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities (link)
  • User controlled data in a document.querySelector("body > div > div.mt-3").innerHTML is an anti-pattern that can lead to XSS vulnerabilities (link)

General comments:

  • On submitpage.php the hidden #CodeInput textarea is no longer bound to the editor as it was with CodeMirror.fromTextArea; make sure you copy the Monaco editor content back into #CodeInput (e.g., in the submit handler) so the backend still receives the code.
  • In the freopen snippet error block you always append an empty div (codeHost) to #ErrorMessage and, in the fallback path, also append a
     directly to #ErrorMessage; consider either rendering the fallback 
     inside codeHost or skipping codeHost creation when Monaco is unavailable to avoid redundant markup.
  • The CodeMirror shim exposes _monacoEditor and callers reach into that to add commands; consider exposing a small public API (e.g., addCommand/triggerSuggest) on the adapter instead of using the private _monacoEditor field to keep the abstraction boundary cleaner.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- On submitpage.php the hidden #CodeInput textarea is no longer bound to the editor as it was with CodeMirror.fromTextArea; make sure you copy the Monaco editor content back into #CodeInput (e.g., in the submit handler) so the backend still receives the code.
- In the freopen snippet error block you always append an empty div (codeHost) to #ErrorMessage and, in the fallback path, also append a <pre> directly to #ErrorMessage; consider either rendering the fallback <pre> inside codeHost or skipping codeHost creation when Monaco is unavailable to avoid redundant markup.
- The CodeMirror shim exposes _monacoEditor and callers reach into that to add commands; consider exposing a small public API (e.g., addCommand/triggerSuggest) on the adapter instead of using the private _monacoEditor field to keep the abstraction boundary cleaner.

## Individual Comments

### Comment 1
<location path="XMOJ.user.js" line_range="374-383" />
<code_context>
+    shim.MergeView = function(container, options) {
</code_context>
<issue_to_address>
**suggestion (bug_risk):** MergeView hardcodes the language to C++, ignoring any mode/language passed in options.

The shim currently instantiates both models with language `'cpp'` and ignores `options.mode` (or any language option), which changes behavior compared to the CodeMirror-based MergeView for non-C++ content. Please derive the Monaco language from the provided mode (similar to `shim`/`createMonacoEditor`, mapping known CodeMirror modes and defaulting to C++) so other languages still get appropriate syntax handling.
</issue_to_address>

### Comment 2
<location path="XMOJ.user.js" line_range="3633-3638" />
<code_context>
                    document.querySelector("body > div > div.mt-3").innerHTML = `<center class="mb-3">` + `<h3>提交代码</h3>` + (SearchParams.get("id") != null ? `题目<span class="blue">${Number(SearchParams.get("id"))}</span>` : `比赛<span class="blue">${Number(SearchParams.get("cid")) + `</span>&emsp;题目<span class="blue">` + String.fromCharCode(65 + parseInt(SearchParams.get("pid")))}</span>`) + `</center>
    <div id="MonacoEditor" style="width:100%; height:400px;"></div>
    <textarea id="CodeInput" style="display:none"></textarea>
    <center class="mt-3">
        <input id="enable_O2" name="enable_O2" type="checkbox"><label for="enable_O2">打开O2开关</label>
        <br>
        <input id="Submit" class="btn btn-info mt-2" type="button" value="提交">
        <div id="ErrorElement" class="mt-2" style="display: none; text-align: left; padding: 10px;">
            <div id="ErrorMessage" style="white-space: pre; background-color: rgba(0, 0, 0, 0.1); padding: 10px; border-radius: 5px;"></div>
            <button id="PassCheck" class="btn btn-outline-secondary mt-2" style="display: none">强制提交</button>
        </div>
    </center>`;
</code_context>
<issue_to_address>
**security (javascript.browser.security.insecure-document-method):** User controlled data in methods like `innerHTML`, `outerHTML` or `document.write` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

### Comment 3
<location path="XMOJ.user.js" line_range="3633-3638" />
<code_context>
                    document.querySelector("body > div > div.mt-3").innerHTML = `<center class="mb-3">` + `<h3>提交代码</h3>` + (SearchParams.get("id") != null ? `题目<span class="blue">${Number(SearchParams.get("id"))}</span>` : `比赛<span class="blue">${Number(SearchParams.get("cid")) + `</span>&emsp;题目<span class="blue">` + String.fromCharCode(65 + parseInt(SearchParams.get("pid")))}</span>`) + `</center>
    <div id="MonacoEditor" style="width:100%; height:400px;"></div>
    <textarea id="CodeInput" style="display:none"></textarea>
    <center class="mt-3">
        <input id="enable_O2" name="enable_O2" type="checkbox"><label for="enable_O2">打开O2开关</label>
        <br>
        <input id="Submit" class="btn btn-info mt-2" type="button" value="提交">
        <div id="ErrorElement" class="mt-2" style="display: none; text-align: left; padding: 10px;">
            <div id="ErrorMessage" style="white-space: pre; background-color: rgba(0, 0, 0, 0.1); padding: 10px; border-radius: 5px;"></div>
            <button id="PassCheck" class="btn btn-outline-secondary mt-2" style="display: none">强制提交</button>
        </div>
    </center>`;
</code_context>
<issue_to_address>
**security (javascript.browser.security.insecure-innerhtml):** User controlled data in a `document.querySelector("body > div > div.mt-3").innerHTML` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread XMOJ.user.js
Comment on lines +374 to +383
shim.MergeView = function(container, options) {
let el = container;
if (typeof container === 'string') el = document.getElementById(container) || document.querySelector(container);
if (!el) { el = document.createElement('div'); document.body.appendChild(el); }
const wrapper = { ignoreWhitespace: !!(options && options.ignoreWhitespace), _diffEditor: null, _originalModel: null, _modifiedModel: null };
(async () => {
try {
await ensureMonaco();
const diffEditor = monaco.editor.createDiffEditor(el, { readOnly: !!(options && options.readOnly), theme: (typeof UtilityEnabled === 'function' && UtilityEnabled("DarkMode") ? 'vs-dark' : 'vs'), minimap: { enabled: false }, automaticLayout: true });
const orig = options && options.value ? options.value : '';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): MergeView hardcodes the language to C++, ignoring any mode/language passed in options.

The shim currently instantiates both models with language 'cpp' and ignores options.mode (or any language option), which changes behavior compared to the CodeMirror-based MergeView for non-C++ content. Please derive the Monaco language from the provided mode (similar to shim/createMonacoEditor, mapping known CodeMirror modes and defaulting to C++) so other languages still get appropriate syntax handling.

Comment thread XMOJ.user.js
Comment on lines 3633 to 3638
document.querySelector("body > div > div.mt-3").innerHTML = `<center class="mb-3">` + `<h3>提交代码</h3>` + (SearchParams.get("id") != null ? `题目<span class="blue">${Number(SearchParams.get("id"))}</span>` : `比赛<span class="blue">${Number(SearchParams.get("cid")) + `</span>&emsp;题目<span class="blue">` + String.fromCharCode(65 + parseInt(SearchParams.get("pid")))}</span>`) + `</center>
<textarea id="CodeInput"></textarea>
<div id="MonacoEditor" style="width:100%; height:400px;"></div>
<textarea id="CodeInput" style="display:none"></textarea>
<center class="mt-3">
<input id="enable_O2" name="enable_O2" type="checkbox"><label for="enable_O2">打开O2开关</label>
<br>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (javascript.browser.security.insecure-document-method): User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

Comment thread XMOJ.user.js
Comment on lines 3633 to 3638
document.querySelector("body > div > div.mt-3").innerHTML = `<center class="mb-3">` + `<h3>提交代码</h3>` + (SearchParams.get("id") != null ? `题目<span class="blue">${Number(SearchParams.get("id"))}</span>` : `比赛<span class="blue">${Number(SearchParams.get("cid")) + `</span>&emsp;题目<span class="blue">` + String.fromCharCode(65 + parseInt(SearchParams.get("pid")))}</span>`) + `</center>
<textarea id="CodeInput"></textarea>
<div id="MonacoEditor" style="width:100%; height:400px;"></div>
<textarea id="CodeInput" style="display:none"></textarea>
<center class="mt-3">
<input id="enable_O2" name="enable_O2" type="checkbox"><label for="enable_O2">打开O2开关</label>
<br>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (javascript.browser.security.insecure-innerhtml): User controlled data in a document.querySelector("body > div > div.mt-3").innerHTML is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New security issues found

Comment thread XMOJ.user.js
Comment on lines 3633 to 3638
document.querySelector("body > div > div.mt-3").innerHTML = `<center class="mb-3">` + `<h3>提交代码</h3>` + (SearchParams.get("id") != null ? `题目<span class="blue">${Number(SearchParams.get("id"))}</span>` : `比赛<span class="blue">${Number(SearchParams.get("cid")) + `</span>&emsp;题目<span class="blue">` + String.fromCharCode(65 + parseInt(SearchParams.get("pid")))}</span>`) + `</center>
<textarea id="CodeInput"></textarea>
<div id="MonacoEditor" style="width:100%; height:400px;"></div>
<textarea id="CodeInput" style="display:none"></textarea>
<center class="mt-3">
<input id="enable_O2" name="enable_O2" type="checkbox"><label for="enable_O2">打开O2开关</label>
<br>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (javascript.browser.security.insecure-document-method): User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

Comment thread XMOJ.user.js
Comment on lines 3633 to 3638
document.querySelector("body > div > div.mt-3").innerHTML = `<center class="mb-3">` + `<h3>提交代码</h3>` + (SearchParams.get("id") != null ? `题目<span class="blue">${Number(SearchParams.get("id"))}</span>` : `比赛<span class="blue">${Number(SearchParams.get("cid")) + `</span>&emsp;题目<span class="blue">` + String.fromCharCode(65 + parseInt(SearchParams.get("pid")))}</span>`) + `</center>
<textarea id="CodeInput"></textarea>
<div id="MonacoEditor" style="width:100%; height:400px;"></div>
<textarea id="CodeInput" style="display:none"></textarea>
<center class="mt-3">
<input id="enable_O2" name="enable_O2" type="checkbox"><label for="enable_O2">打开O2开关</label>
<br>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (javascript.browser.security.insecure-innerhtml): User controlled data in a document.querySelector("body > div > div.mt-3").innerHTML is an anti-pattern that can lead to XSS vulnerabilities

Source: opengrep

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="package.json">

<violation number="1" location="package.json:3">
P2: Manual version bump in `package.json` violates the project's automated version sync contract. Project conventions state version numbers must never be edited manually — version bumps are handled automatically by GitHub Actions when PRs modify `XMOJ.user.js`. A manual edit here may desync `package.json` from `XMOJ.user.js` and `Update.json` after the automated workflow runs.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread package.json
{
"name": "xmoj-script",
"version": "3.5.1",
"version": "3.5.2",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Manual version bump in package.json violates the project's automated version sync contract. Project conventions state version numbers must never be edited manually — version bumps are handled automatically by GitHub Actions when PRs modify XMOJ.user.js. A manual edit here may desync package.json from XMOJ.user.js and Update.json after the automated workflow runs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At package.json, line 3:

<comment>Manual version bump in `package.json` violates the project's automated version sync contract. Project conventions state version numbers must never be edited manually — version bumps are handled automatically by GitHub Actions when PRs modify `XMOJ.user.js`. A manual edit here may desync `package.json` from `XMOJ.user.js` and `Update.json` after the automated workflow runs.</comment>

<file context>
@@ -1,6 +1,6 @@
 {
   "name": "xmoj-script",
-  "version": "3.5.1",
+  "version": "3.5.2",
   "description": "an improvement script for xmoj.tech",
   "main": "AddonScript.js",
</file context>
Suggested change
"version": "3.5.2",
"version": "3.5.1",

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="XMOJ.user.js">

<violation number="1" location="XMOJ.user.js:264">
P2: Monaco bootstrap fallback can hang forever because the polling Promise has no timeout/reject path.</violation>

<violation number="2" location="XMOJ.user.js:387">
P2: MergeView hardcodes `'cpp'` as the language for both models, ignoring any `options.mode` or `options.language` that may be passed in. This diverges from the behavior of the regular shim/`createMonacoEditor` which maps `options.mode` to a Monaco language. Derive the language from options (e.g., `const lang = options && options.mode === 'text/x-c++src' ? 'cpp' : (options && options.language || 'cpp');`) so non-C++ content receives appropriate syntax highlighting.</violation>

<violation number="3" location="XMOJ.user.js:3649">
P1: Submit page has no fallback when Monaco initialization fails, which can break code submission entirely on loader/CDN errors.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread XMOJ.user.js
})
})();
CodeMirrorElement.setSize("100%", "auto");
CodeMirrorElement = await createMonacoEditor('MonacoEditor', {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Submit page has no fallback when Monaco initialization fails, which can break code submission entirely on loader/CDN errors.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At XMOJ.user.js, line 3649:

<comment>Submit page has no fallback when Monaco initialization fails, which can break code submission entirely on loader/CDN errors.</comment>

<file context>
@@ -3489,24 +3646,21 @@ async function main() {
-                        })
-                    })();
-                    CodeMirrorElement.setSize("100%", "auto");
+                    CodeMirrorElement = await createMonacoEditor('MonacoEditor', {
+                        language: 'cpp',
+                        value: '',
</file context>

Comment thread XMOJ.user.js
const mod = options && options.orig ? options.orig : '';
const origVal = wrapper.ignoreWhitespace ? orig.replace(/\s+/g,' ') : orig;
const modVal = wrapper.ignoreWhitespace ? mod.replace(/\s+/g,' ') : mod;
const originalModel = monaco.editor.createModel(origVal, 'cpp');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: MergeView hardcodes 'cpp' as the language for both models, ignoring any options.mode or options.language that may be passed in. This diverges from the behavior of the regular shim/createMonacoEditor which maps options.mode to a Monaco language. Derive the language from options (e.g., const lang = options && options.mode === 'text/x-c++src' ? 'cpp' : (options && options.language || 'cpp');) so non-C++ content receives appropriate syntax highlighting.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At XMOJ.user.js, line 387:

<comment>MergeView hardcodes `'cpp'` as the language for both models, ignoring any `options.mode` or `options.language` that may be passed in. This diverges from the behavior of the regular shim/`createMonacoEditor` which maps `options.mode` to a Monaco language. Derive the language from options (e.g., `const lang = options && options.mode === 'text/x-c++src' ? 'cpp' : (options && options.language || 'cpp');`) so non-C++ content receives appropriate syntax highlighting.</comment>

<file context>
@@ -240,6 +240,162 @@ let GetUserBadge = async (Username) => {
+                const mod = options && options.orig ? options.orig : '';
+                const origVal = wrapper.ignoreWhitespace ? orig.replace(/\s+/g,' ') : orig;
+                const modVal = wrapper.ignoreWhitespace ? mod.replace(/\s+/g,' ') : mod;
+                const originalModel = monaco.editor.createModel(origVal, 'cpp');
+                const modifiedModel = monaco.editor.createModel(modVal, 'cpp');
+                diffEditor.setModel({ original: originalModel, modified: modifiedModel });
</file context>

Comment thread XMOJ.user.js
try {
require(['vs/editor/editor.main'], function() { resolve(); });
} catch (e) {
const check = setInterval(() => { if (typeof monaco !== 'undefined') { clearInterval(check); resolve(); } }, 50);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Monaco bootstrap fallback can hang forever because the polling Promise has no timeout/reject path.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At XMOJ.user.js, line 264:

<comment>Monaco bootstrap fallback can hang forever because the polling Promise has no timeout/reject path.</comment>

<file context>
@@ -240,6 +240,162 @@ let GetUserBadge = async (Username) => {
+        try {
+            require(['vs/editor/editor.main'], function() { resolve(); });
+        } catch (e) {
+            const check = setInterval(() => { if (typeof monaco !== 'undefined') { clearInterval(check); resolve(); } }, 50);
+        }
+    });
</file context>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L user-script This issue or pull request is related to the main user script

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant