sync: dev to extern-contrib#990
Conversation
…nt (#989) * Use Monaco Editor and save code in submitpage.php when edit the content. * 3.5.2 * Update version info to 3.5.2 * Fix AI-detected bugs: Monaco timeout, MergeView language, XSS, fallback editor, package.json version * Fix code review issues: MergeView language expression, em space comment, fallback interface stubs * Bump version from 3.5.1 to 3.5.2 Signed-off-by: Shan Wenxiao <seanoj_noreply@yeah.net> * Update time and description of 3.5.2 * Fix constant condition: replace dead typeof check with fallback '80px' in setSize * Update time and description of 3.5.2 * Update XMOJ.user.js Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> Signed-off-by: Shan Wenxiao <seanoj_noreply@yeah.net> * Update time and description of 3.5.2 * Fix 3 AI review bugs: ignoreWhitespace newlines, setSize replay, fallback persistence * Update time and description of 3.5.2 * Remove rounded corners style from Monaco editor Removed custom style for rounded corners in the Monaco editor. Signed-off-by: zsTree <233546082+def-WA2025@users.noreply.github.com> * Update time and description of 3.5.2 * Update time and description of 3.5.2 * Update XMOJ.user.js Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: zsTree <233546082+def-WA2025@users.noreply.github.com> * Update time and description of 3.5.2 * Increase Monaco editor and fallback textarea height Updated the size of the Monaco editor and fallback textarea to 550px. Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Fix typo in FileSaver.js URL Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Enhance localStorage handling and editor dimensions Added fallback key logic for localStorage retrieval and adjusted Monaco editor height. Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Fix condition for checking saved localStorage value Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Implement auto-fit for Monaco editor and loading UI Enhance Monaco editor integration with auto-fit feature and loading placeholder Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Refactor options handling for improved clarity Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Update XMOJ.user.js Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Define options in createMonacoEditor function Ensure options is always defined in createMonacoEditor. Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Refactor options handling in Monaco editor functions Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Enhance dispose function for better resource management Refactor dispose function to include editor cleanup and model disposal. Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Refactor Monaco editor initialization and disposal Removed the creation of a custom style element for Monaco editor. Added error handling for disposing transient Monaco editors in various functions. Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Simplify error message editor disposal logic Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Modify applyAutoFit function to accept editor parameter Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Update theme from 'darcula' to 'vs-dark' & Use Cloudflare cdnjs Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Simplify submission key retrieval logic Removed unused localStorage fallback logic for submission key. Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 * Improve error handling and user feedback Enhanced error handling by adding console error logging and user alerts in DebugMode for various operations. Signed-off-by: zsTree <wa2025666@gmail.com> * Update time and description of 3.5.2 --------- Signed-off-by: Shan Wenxiao <seanoj_noreply@yeah.net> Signed-off-by: zsTree <233546082+def-WA2025@users.noreply.github.com> Signed-off-by: zsTree <wa2025666@gmail.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Shan Wenxiao <seanoj_noreply@yeah.net> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Reviewer's GuideReplaces most CodeMirror usage with a Monaco-based editor integration for code submission and viewing, including dynamic Monaco loading, viewport-fitting layout, localStorage-backed persistence, and safer CE/standard-solution rendering, while bumping the script version to 3.5.2. Sequence diagram for Monaco editor initialization on submit pagesequenceDiagram
actor User
participant Browser
participant XMOJ_main as main
participant ensureMonaco
participant MonacoCDN
participant createMonacoEditor
participant monaco as monaco.editor
participant FallbackTA as CodeInput_textarea
User->>Browser: Open /submitpage.php
Browser->>XMOJ_main: execute main()
XMOJ_main->>Browser: Set submit page HTML (MonacoEditor, CodeInput)
XMOJ_main->>createMonacoEditor: await createMonacoEditor('MonacoEditor', editorOptions)
createMonacoEditor->>ensureMonaco: await ensureMonaco()
alt monaco not loaded
ensureMonaco->>MonacoCDN: load loader.js
MonacoCDN-->>ensureMonaco: loader.js loaded
ensureMonaco->>Browser: require.config({ paths: { vs: MonacoCDN } })
ensureMonaco->>Browser: require(['vs/editor/editor.main'])
Browser-->>ensureMonaco: monaco defined
else monaco already available
ensureMonaco-->>createMonacoEditor: return
end
createMonacoEditor->>Browser: monaco.editor.create(innerHost, options)
Browser-->>createMonacoEditor: editor instance
createMonacoEditor-->>XMOJ_main: Monaco adapter (CodeMirrorElement)
XMOJ_main->>monaco: addCommand(Ctrl+Enter, Submit.click)
XMOJ_main->>Browser: remove loadEditor placeholder
rect rgb(245,245,245)
alt Monaco initialization throws
createMonacoEditor--x XMOJ_main: throw error
XMOJ_main->>Browser: hide MonacoEditor, show CodeInput
XMOJ_main->>FallbackTA: attach input/keydown handlers
XMOJ_main-->>User: Fallback plain textarea editor
end
end
Sequence diagram for CE error message Monaco snippet lifecyclesequenceDiagram
participant Submit as Submit_button
participant XMOJ_main as main
participant _xmoj_dispose as _xmoj_disposeErrorMessageEditors
participant ErrorMessage
participant monaco as monaco.editor
Submit->>XMOJ_main: Submit code
XMOJ_main-->>Submit: Receive compile error (Response.stderr)
XMOJ_main->>ErrorMessage: show error text
XMOJ_main->>_xmoj_dispose: _xmoj_disposeErrorMessageEditors()
_xmoj_dispose->>_xmoj_dispose: dispose window._xmoj_temp_error_editors
_xmoj_dispose->>_xmoj_dispose: clean hosts with data-xmoj-error-editor
XMOJ_main->>ErrorMessage: append copyFreopenButton
XMOJ_main->>ErrorMessage: append codeHost div
alt monaco available
XMOJ_main->>monaco: monaco.editor.create(codeHost, { readOnly: true, language: 'cpp' })
monaco-->>XMOJ_main: _tmpErrEditor
XMOJ_main->>_xmoj_dispose: push _tmpErrEditor to window._xmoj_temp_error_editors
XMOJ_main->>ErrorMessage: mark host data-xmoj-error-editor
else monaco not available
XMOJ_main->>ErrorMessage: append pre with freopen snippet
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Deploying xmoj-script-dev-channel with
|
| Latest commit: |
1ca8d17
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://183dcf7d.xmoj-script-dev-channel.pages.dev |
There was a problem hiding this comment.
Hey - I've found 2 issues, and left some high level feedback:
- There is a large amount of duplicated try/catch +
UtilityEnabled('DebugMode')+SmartAlert(...)error handling throughout the new Monaco integration; consider extracting this into a small helper (e.g.logDebugError(e, context)) to reduce repetition and make future changes to the message or behavior centralized. ensureMonacoassumes a globalrequire/AMD loader and callsrequire.configdirectly; it may be safer to guard against other libraries’requireimplementations or namespace Monaco’s loader to avoid conflicts in pages that definerequirefor other purposes.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- There is a large amount of duplicated try/catch + `UtilityEnabled('DebugMode')` + `SmartAlert(...)` error handling throughout the new Monaco integration; consider extracting this into a small helper (e.g. `logDebugError(e, context)`) to reduce repetition and make future changes to the message or behavior centralized.
- `ensureMonaco` assumes a global `require`/AMD loader and calls `require.config` directly; it may be safer to guard against other libraries’ `require` implementations or namespace Monaco’s loader to avoid conflicts in pages that define `require` for other purposes.
## Individual Comments
### Comment 1
<location path="XMOJ.user.js" line_range="5476" />
<code_context>
- let Temp = ParsedDocument.getElementsByTagName("pre");
- document.querySelector("body > div > div.mt-3").innerHTML = "";
- for (let i = 0; i < Temp.length; i++) {
+ if (!ParsedDocument.getElementsByClassName("jumbotron")[0].innerHTML.includes('I am sorry, You could not view this message!')) {
+ document.querySelector("body > div > div.mt-3").innerHTML = "";
let CodeElement = document.createElement("div");
</code_context>
<issue_to_address>
**issue (bug_risk):** Guard against missing `.jumbotron` elements before accessing `[0].innerHTML`.
This assumes `getElementsByClassName("jumbotron")[0]` always exists. If the CEInfo layout changes or the element is missing, `[0]` will be `undefined` and accessing `.innerHTML` will throw. Instead, assign it to a variable and guard before use, e.g.
```js
const jumbo = ParsedDocument.getElementsByClassName("jumbotron")[0];
if (!jumbo || jumbo.innerHTML.includes('I am sorry, You could not view this message!')) {
return; // handle restricted view / missing jumbotron
}
```
Apply the same defensive check for the `problem_std.php` usage as well.
</issue_to_address>
### Comment 2
<location path="XMOJ.user.js" line_range="5496" />
<code_context>
+ return Response.text();
+ }).then((Response) => {
+ let ParsedDocument = new DOMParser().parseFromString(Response, "text/html");
+ if (!ParsedDocument.getElementsByClassName("jumbotron")[0].innerHTML.includes('No such Problem!')) {
+ let Temp = ParsedDocument.getElementsByTagName("pre");
+ document.querySelector("body > div > div.mt-3").innerHTML = "";
</code_context>
<issue_to_address>
**issue:** Add a null check for the `jumbotron` element on the problem_std page.
This code assumes `getElementsByClassName("jumbotron")[0]` always exists. If the element is missing or the class changes, this will throw. Consider guarding the lookup:
```js
const jumbo = ParsedDocument.getElementsByClassName("jumbotron")[0];
if (!jumbo || jumbo.innerHTML.includes('No such Problem!')) {
return;
}
```
This preserves the early return while preventing a null access error.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| let Temp = ParsedDocument.getElementsByTagName("pre"); | ||
| document.querySelector("body > div > div.mt-3").innerHTML = ""; | ||
| for (let i = 0; i < Temp.length; i++) { | ||
| if (!ParsedDocument.getElementsByClassName("jumbotron")[0].innerHTML.includes('I am sorry, You could not view this message!')) { |
There was a problem hiding this comment.
issue (bug_risk): Guard against missing .jumbotron elements before accessing [0].innerHTML.
This assumes getElementsByClassName("jumbotron")[0] always exists. If the CEInfo layout changes or the element is missing, [0] will be undefined and accessing .innerHTML will throw. Instead, assign it to a variable and guard before use, e.g.
const jumbo = ParsedDocument.getElementsByClassName("jumbotron")[0];
if (!jumbo || jumbo.innerHTML.includes('I am sorry, You could not view this message!')) {
return; // handle restricted view / missing jumbotron
}Apply the same defensive check for the problem_std.php usage as well.
| return Response.text(); | ||
| }).then((Response) => { | ||
| let ParsedDocument = new DOMParser().parseFromString(Response, "text/html"); | ||
| if (!ParsedDocument.getElementsByClassName("jumbotron")[0].innerHTML.includes('No such Problem!')) { |
There was a problem hiding this comment.
issue: Add a null check for the jumbotron element on the problem_std page.
This code assumes getElementsByClassName("jumbotron")[0] always exists. If the element is missing or the class changes, this will throw. Consider guarding the lookup:
const jumbo = ParsedDocument.getElementsByClassName("jumbotron")[0];
if (!jumbo || jumbo.innerHTML.includes('No such Problem!')) {
return;
}This preserves the early return while preventing a null access error.
sync-branches: New code has just landed in dev, so let's bring extern-contrib up to speed!
Summary by Sourcery
Switch the XMOJ userscript code viewing and submission experience to a Monaco-based editor while keeping a CodeMirror-compatible shim and update metadata to 3.5.2.
Enhancements:
Build:
Summary by cubic
Replaced the submit editor with
monaco-editorfor a faster, more reliable coding experience, with autosave and a responsive layout. Added safe fallbacks and improved error displays; bumped version to 3.5.2.New Features
monaco-editoronsubmitpage.phpwith localStorage autosave, Ctrl+Enter submit, and auto-fit height.vs-dark.Bug Fixes
Written for commit 1ca8d17. Summary will update on new commits.