Skip to content

feat: Modernize project with Vite and modular structure#846

Closed
google-labs-jules[bot] wants to merge 3 commits intodevfrom
feat/vite-refactor
Closed

feat: Modernize project with Vite and modular structure#846
google-labs-jules[bot] wants to merge 3 commits intodevfrom
feat/vite-refactor

Conversation

@google-labs-jules
Copy link

This refactoring modernizes the XMOJ-Script project by introducing Vite as a bundler, modularizing the codebase, and adopting a standard project structure. It also includes updates to the CI/CD workflow and dependency management.

This commit introduces a complete refactoring of the XMOJ-Script project to use modern development practices and Vite as a bundler.

- **Build System:** The project now uses Vite for bundling, with a `vite.config.js` and npm scripts for development, building, and previewing.

- **Project Structure:** The codebase has been reorganized into a standard `src` and `public` directory structure.

- **Modularization:** The monolithic userscript has been broken down into multiple, smaller modules for better maintainability and readability. This includes utility functions, API calls, styles, and page-specific logic.

- **Dependency Management:** All external libraries are now managed as npm dependencies in `package.json`.

- **CI/CD:** The GitHub Actions workflow has been updated to use the new `npm run build` command for releases.

- **Cleanup:** Removed old, unused, and garbage files.
@boomzero boomzero changed the base branch from master to dev August 26, 2025 12:01
This commit introduces a complete refactoring of the XMOJ-Script project to use modern development practices and Vite as a bundler.

- **Build System:** The project now uses Vite for bundling, with a `vite.config.js` and npm scripts for development, building, and previewing.

- **Project Structure:** The codebase has been reorganized into a standard `src` and `public` directory structure.

- **Modularization:** The monolithic userscript has been broken down into multiple, smaller modules for better maintainability and readability. This includes utility functions, API calls, styles, and page-specific logic.

- **Dependency Management:** All external libraries are now managed as npm dependencies in `package.json`.

- **CI/CD:** The GitHub Actions workflow has been updated to use the new `npm run build` command for releases.

- **Cleanup:** Removed old, unused, and garbage files.

**CI Fix:**
- Restored `Update.json` which was deleted during refactoring but is required by the `UpdateVersion` CI job.
- Updated `Update/UpdateVersion.js` to look for the built userscript in the `dist` directory.
- Added a build step to the `UpdateVersion.yml` workflow to ensure the userscript is built before the versioning script is run.
@hendragon-bot hendragon-bot bot added GitHub-related user-script This issue or pull request is related to the main user script update-script Related to our update infrastructure! addon-script This issue or pull request is related to the addon script labels Aug 26, 2025
}
console.log("Submitting problem " + PID);
Submitted = true;
AutoCheatButton.innerHTML = "正在提交 " + PID;

Check warning

Code scanning / CodeQL

DOM text reinterpreted as HTML Medium

DOM text
is reinterpreted as HTML without escaping meta-characters.

Copilot Autofix

AI 7 months ago

General Approach:

  • Do not pass potentially attacker-controlled or unsanitized DOM text directly into .innerHTML.
  • Instead, either (a) set safe text using the .innerText or .textContent property, or (b) escape any special HTML characters before assigning to .innerHTML.

Detailed Best Fix:

  • On line 189, change the assignment from AutoCheatButton.innerHTML = "正在提交 " + PID; to using AutoCheatButton.innerText = "正在提交 " + PID;.
    • This completely avoids HTML interpretation, so even if PID contains malicious code or markup, it is printed as plain text.
    • Existing functionality (displaying the loading message) is preserved.

File/Lines to Change:

  • Only one line needs to be changed: in src/pages/contest.js, update line 189.

Implementation Needs:

  • No new imports or extra functions are required, just change .innerHTML to .innerText.

Suggested changeset 1
src/pages/contest.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/pages/contest.js b/src/pages/contest.js
--- a/src/pages/contest.js
+++ b/src/pages/contest.js
@@ -186,7 +186,7 @@
                         }
                         console.log("Submitting problem " + PID);
                         Submitted = true;
-                        AutoCheatButton.innerHTML = "正在提交 " + PID;
+                        AutoCheatButton.innerText = "正在提交 " + PID;
                         let SID = 0;
                         await fetch("https://www.xmoj.tech/status.php?problem_id=" + PID + "&jresult=4")
                             .then((Result) => {
EOF
@@ -186,7 +186,7 @@
}
console.log("Submitting problem " + PID);
Submitted = true;
AutoCheatButton.innerHTML = "正在提交 " + PID;
AutoCheatButton.innerText = "正在提交 " + PID;
let SID = 0;
await fetch("https://www.xmoj.tech/status.php?problem_id=" + PID + "&jresult=4")
.then((Result) => {
Copilot is powered by AI and may make mistakes. Always verify output.
}
}
if (document.getElementById(ID) !== null) {
document.getElementById(ID).innerHTML = HTMLData;

Check failure

Code scanning / CodeQL

Client-side cross-site scripting High

Cross-site scripting vulnerability due to
user-provided value
.

Copilot Autofix

AI 7 months ago

To fix this DOM-based XSS vulnerability, all direct insertions of untrusted Username data into HTML markup should be properly escaped or replaced with safe alternatives. When concatenating user data (such as Username) into HTML attribute values (e.g., within <a href=...>), the value must be HTML-escaped to prevent breaking out of attributes or tags. Similarly, any use of user data within inline CSS or within badge contents should also be encoded/sanitized if not controlled.

Specifically, within GetUsernameHTML in src/utils.js, we should:

  1. Use the provided escapeHTML function to encode Username before inserting it into the href attribute and elsewhere in the markup string.
  2. Optionally, also encode other possibly user-controllable strings (such as colors in <span style>, although if these are only from trusted badge data this may not be necessary).
  3. Replace all ${Username} interpolations within markup strings with ${escapeHTML(Username)}.

No new dependencies are needed, as the existing escapeHTML implementation suffices.


Suggested changeset 1
src/utils.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/utils.js b/src/utils.js
--- a/src/utils.js
+++ b/src/utils.js
@@ -204,7 +204,7 @@
             }
             HTMLData += `" class="rounded me-2" style="width: 20px; height: 20px; ">`;
         }
-        HTMLData += `<a href="${Href}${Username}" class="link-offset-2 link-underline-opacity-50 `
+        HTMLData += `<a href="${Href}${escapeHTML(Username)}" class="link-offset-2 link-underline-opacity-50 `
         if (UtilityEnabled("Rating")) {
             let Rating = UserInfo.Rating;
             // if(AdminUserList.includes(Username)){
EOF
@@ -204,7 +204,7 @@
}
HTMLData += `" class="rounded me-2" style="width: 20px; height: 20px; ">`;
}
HTMLData += `<a href="${Href}${Username}" class="link-offset-2 link-underline-opacity-50 `
HTMLData += `<a href="${Href}${escapeHTML(Username)}" class="link-offset-2 link-underline-opacity-50 `
if (UtilityEnabled("Rating")) {
let Rating = UserInfo.Rating;
// if(AdminUserList.includes(Username)){
Copilot is powered by AI and may make mistakes. Always verify output.
}
}
if (document.getElementById(ID) !== null) {
document.getElementById(ID).innerHTML = HTMLData;

Check warning

Code scanning / CodeQL

DOM text reinterpreted as HTML Medium

DOM text
is reinterpreted as HTML without escaping meta-characters.
DOM text
is reinterpreted as HTML without escaping meta-characters.
DOM text
is reinterpreted as HTML without escaping meta-characters.

Copilot Autofix

AI 7 months ago

To address the vulnerability, we need to ensure untrusted input (Username) is properly escaped before inclusion as HTML. The best fix is to apply the escapeHTML utility function to Username whenever it is interpolated into HTML markup destined for innerHTML. Specifically, in GetUsernameHTML, this affects the anchor href attribute and elsewhere Username is embedded directly in markup. Since attribute contexts (href) should not be vulnerable to tag-breaking if properly escaped (with escapeHTML), the fix will replace e.g. ${Username} in any HTML string construction for innerHTML with ${escapeHTML(Username)}.

Required changes:

  • Update GetUsernameHTML in src/utils.js.
  • Use escapeHTML for all interpolations of Username inside HTML assigned via innerHTML.
  • Ensure the fix does not alter usages where data is added as a text node (already safe).

Method/imports needed:
No imports required—escapeHTML is already defined in the same file.


Suggested changeset 1
src/utils.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/utils.js b/src/utils.js
--- a/src/utils.js
+++ b/src/utils.js
@@ -204,7 +204,7 @@
             }
             HTMLData += `" class="rounded me-2" style="width: 20px; height: 20px; ">`;
         }
-        HTMLData += `<a href="${Href}${Username}" class="link-offset-2 link-underline-opacity-50 `
+        HTMLData += `<a href="${Href}${escapeHTML(Username)}" class="link-offset-2 link-underline-opacity-50 `
         if (UtilityEnabled("Rating")) {
             let Rating = UserInfo.Rating;
             // if(AdminUserList.includes(Username)){
@@ -230,7 +230,7 @@
             }
             let BadgeInfo = await GetUserBadge(Username);
             if (BadgeInfo.Content != "") {
-                HTMLData += `<span class="badge ms-2" style="background-color: ${BadgeInfo.BackgroundColor}; color: ${BadgeInfo.Color}">${BadgeInfo.Content}</span>`;
+                HTMLData += `<span class="badge ms-2" style="background-color: ${escapeHTML(BadgeInfo.BackgroundColor)}; color: ${escapeHTML(BadgeInfo.Color)}">${escapeHTML(BadgeInfo.Content)}</span>`;
             }
         }
         if (document.getElementById(ID) !== null) {
EOF
@@ -204,7 +204,7 @@
}
HTMLData += `" class="rounded me-2" style="width: 20px; height: 20px; ">`;
}
HTMLData += `<a href="${Href}${Username}" class="link-offset-2 link-underline-opacity-50 `
HTMLData += `<a href="${Href}${escapeHTML(Username)}" class="link-offset-2 link-underline-opacity-50 `
if (UtilityEnabled("Rating")) {
let Rating = UserInfo.Rating;
// if(AdminUserList.includes(Username)){
@@ -230,7 +230,7 @@
}
let BadgeInfo = await GetUserBadge(Username);
if (BadgeInfo.Content != "") {
HTMLData += `<span class="badge ms-2" style="background-color: ${BadgeInfo.BackgroundColor}; color: ${BadgeInfo.Color}">${BadgeInfo.Content}</span>`;
HTMLData += `<span class="badge ms-2" style="background-color: ${escapeHTML(BadgeInfo.BackgroundColor)}; color: ${escapeHTML(BadgeInfo.Color)}">${escapeHTML(BadgeInfo.Content)}</span>`;
}
}
if (document.getElementById(ID) !== null) {
Copilot is powered by AI and may make mistakes. Always verify output.
This commit introduces a complete refactoring of the XMOJ-Script project to use modern development practices and Vite as a bundler.

- **Build System:** The project now uses Vite for bundling, with a `vite.config.js` and npm scripts for development, building, and previewing.

- **Project Structure:** The codebase has been reorganized into a standard `src` and `public` directory structure.

- **Modularization:** The monolithic userscript has been broken down into multiple, smaller modules for better maintainability and readability. This includes utility functions, API calls, styles, and page-specific logic.

- **Dependency Management:** All external libraries are now managed as npm dependencies in `package.json`.

- **CI/CD:** The GitHub Actions workflow has been updated to use the new `npm run build` command for releases.

- **Cleanup:** Removed old, unused, and garbage files.

**CI Fix:**
- Restored `Update.json` with full historical data, which was deleted during refactoring but is required by the `UpdateVersion` CI job.
- Updated `Update/UpdateVersion.js` to look for the built userscript in the `dist` directory.
- Added a build step to the `UpdateVersion.yml` workflow to ensure the userscript is built before the versioning script is run.
@hendragon-bot hendragon-bot bot added the stale Hurry up! label Sep 10, 2025
@hendragon-bot hendragon-bot bot closed this Sep 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

addon-script This issue or pull request is related to the addon script GitHub-related size/XXL stale Hurry up! update-script Related to our update infrastructure! 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.

0 participants