Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f95463a
Update diff-match-patch library source URL
boomzero Aug 11, 2025
ebd7590
Merge branch 'dev' into boomzero/ncdn
boomzero Aug 11, 2025
9573bab
2.1.1
github-actions[bot] Aug 11, 2025
0176b58
Update version info to 2.1.1
github-actions[bot] Aug 11, 2025
a0cdcf7
Update time and description of 2.1.1
github-actions[bot] Aug 11, 2025
9718a36
Merge pull request #829 from XMOJ-Script-dev/boomzero/ncdn
boomzero Aug 11, 2025
8db0106
Bump JetBrains/qodana-action from 2024.3 to 2025.2
dependabot[bot] Aug 18, 2025
8bcdcc1
Bump actions/checkout from 2 to 5
dependabot[bot] Aug 18, 2025
a7106e7
fix: avoid top-level await in credential helpers
boomzero Aug 19, 2025
33a44f8
2.1.2
github-actions[bot] Aug 19, 2025
76260d1
Update version info to 2.1.2
github-actions[bot] Aug 19, 2025
ca06a1e
Merge pull request #834 from XMOJ-Script-dev/codex/upgrade-password-s…
boomzero Aug 19, 2025
764be5c
feat: configure theme from settings
boomzero Aug 19, 2025
b8fb960
2.1.3
github-actions[bot] Aug 19, 2025
1bb4065
Update version info to 2.1.3
github-actions[bot] Aug 19, 2025
8539b7f
Update time and description of 2.1.3
github-actions[bot] Aug 19, 2025
6698900
Merge pull request #835 from XMOJ-Script-dev/codex/add-automatic-them…
boomzero Aug 19, 2025
2d9b2bb
Merge pull request #831 from XMOJ-Script-dev/dependabot/github_action…
boomzero Aug 19, 2025
fb83b32
Merge pull request #832 from XMOJ-Script-dev/dependabot/github_action…
boomzero Aug 19, 2025
45e69ba
2.2.0
github-actions[bot] Aug 21, 2025
b7e1fae
Update to release 2.2.0
github-actions[bot] Aug 21, 2025
7df266e
Merge pull request #837 from XMOJ-Script-dev/actions/temp
boomzero Aug 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/AutoLabelIssue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Generate a token
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/CodeQL.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: github/codeql-action/init@v3
with:
languages: "javascript"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/DependencyScan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: actions/dependency-review-action@v4
2 changes: 1 addition & 1 deletion .github/workflows/Prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
with:
node-version: 16
registry-url: https://registry.npmjs.org/
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Publish to npm
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/Release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
with:
node-version: 16
registry-url: https://registry.npmjs.org/
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Get version
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/UpdateToRelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
pull-requests: write
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Update to release
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/UpdateVersion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ jobs:
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Update version
run: node ./Update/UpdateVersion.js ${{ steps.generate_token.outputs.token }} ${{ github.event.number }} "${{ github.event.pull_request.title }}"
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ jobs:
pull-requests: write
checks: write
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v5
with:
ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit
fetch-depth: 0 # a full history is required for pull request analysis
- name: 'Qodana Scan'
uses: JetBrains/qodana-action@v2024.3
uses: JetBrains/qodana-action@v2025.2
env:
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
2 changes: 1 addition & 1 deletion .github/workflows/sync-to-extern-contrib.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
name: Syncing branches
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v5
- name: Set up Node
uses: actions/setup-node@v4
with:
Expand Down
52 changes: 52 additions & 0 deletions Update.json
Original file line number Diff line number Diff line change
Expand Up @@ -2969,6 +2969,58 @@
}
],
"Notes": "No release notes were provided for this release."
},
"2.1.1": {
"UpdateDate": 1754911555185,
"Prerelease": true,
"UpdateContents": [
{
"PR": 829,
"Description": "Update diff-match-patch library source URL"
}
],
"Notes": "No release notes were provided for this release."
},
"2.1.2": {
"UpdateDate": 1755589063111,
"Prerelease": true,
"UpdateContents": [
{
"PR": 834,
"Description": "feat: use credential management api"
}
],
"Notes": "No release notes were provided for this release."
},
"2.1.3": {
"UpdateDate": 1755596470421,
"Prerelease": true,
"UpdateContents": [
{
"PR": 835,
"Description": "feat: add user-selectable theme"
}
],
"Notes": "No release notes were provided for this release."
},
"2.2.0": {
"UpdateDate": 1755767075588,
"Prerelease": false,
"UpdateContents": [
{
"PR": 829,
"Description": "Update diff-match-patch library source URL"
},
{
"PR": 834,
"Description": "feat: use credential management api"
},
{
"PR": 835,
"Description": "feat: add user-selectable theme"
}
],
"Notes": "No release notes were provided for this release."
}
}
}
106 changes: 90 additions & 16 deletions XMOJ.user.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// ==UserScript==
// @name XMOJ
// @version 2.1.0
// @version 2.2.0
// @description XMOJ增强脚本
// @author @XMOJ-Script-dev, @langningchen and the community
// @namespace https://github/langningchen
Expand All @@ -10,7 +10,7 @@
// @require https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/codemirror.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/mode/clike/clike.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/addon/merge/merge.min.js
// @require https://cdn.jsdelivr.net/gh/google/diff-match-patch@master/javascript/diff_match_patch_uncompressed.js
// @require https://gitee.com/mirrors_google/diff-match-patch/raw/master/javascript/diff_match_patch_uncompressed.js
// @require https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.0.2/purify.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/marked/4.3.0/marked.min.js
Expand Down Expand Up @@ -441,6 +441,35 @@ let UtilityEnabled = (Name) => {
}
}
};
let storeCredential = async (username, password) => {
if ('credentials' in navigator && window.PasswordCredential) {
try {
const credential = new PasswordCredential({ id: username, password: password });
await navigator.credentials.store(credential);
} catch (e) {
console.error(e);
}
}
};
let getCredential = async () => {
if ('credentials' in navigator && window.PasswordCredential) {
try {
return await navigator.credentials.get({ password: true, mediation: 'optional' });
} catch (e) {
console.error(e);
}
}
return null;
};
let clearCredential = async () => {
if ('credentials' in navigator && window.PasswordCredential) {
try {
await navigator.credentials.preventSilentAccess();
} catch (e) {
console.error(e);
}
}
};
let RequestAPI = (Action, Data, CallBack) => {
try {
let Session = "";
Expand Down Expand Up @@ -523,6 +552,24 @@ let CurrentUsername = document.querySelector("#profile").innerText;
CurrentUsername = CurrentUsername.replaceAll(/[^a-zA-Z0-9]/g, "");
let IsAdmin = AdminUserList.indexOf(CurrentUsername) !== -1;

const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
const applyTheme = (theme) => {
document.querySelector("html").setAttribute("data-bs-theme", theme);
localStorage.setItem("UserScript-Setting-DarkMode", theme === "dark" ? "true" : "false");
};
const applySystemTheme = (e) => applyTheme(e.matches ? "dark" : "light");
let initTheme = () => {
const saved = localStorage.getItem("UserScript-Setting-Theme") || "auto";
if (saved === "auto") {
applyTheme(prefersDark.matches ? "dark" : "light");
prefersDark.addEventListener("change", applySystemTheme);
} else {
applyTheme(saved);
prefersDark.removeEventListener("change", applySystemTheme);
}
};
initTheme();


class NavbarStyler {
constructor() {
Expand Down Expand Up @@ -962,8 +1009,7 @@ async function main() {
location.href = "https://www.xmoj.tech/modifypage.php?ByUserScript=1";
});
PopupUL.children[5].addEventListener("click", () => {
localStorage.removeItem("UserScript-Username");
localStorage.removeItem("UserScript-Password");
clearCredential();
document.cookie = "PHPSESSID=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/"; //This is how you remove a cookie?
location.href = "https://www.xmoj.tech/logout.php";
});
Expand Down Expand Up @@ -1331,7 +1377,32 @@ async function main() {
} else if (Data[i].Type == "D") {
Row.classList.add("list-group-item-danger");
}
if (Data[i].Children == undefined) {
if (Data[i].ID == "Theme") {
let Label = document.createElement("label");
Label.classList.add("me-2");
Label.htmlFor = "UserScript-Setting-Theme";
Label.innerText = Data[i].Name;
Row.appendChild(Label);
let Select = document.createElement("select");
Select.classList.add("form-select", "form-select-sm", "w-auto", "d-inline");
Select.id = "UserScript-Setting-Theme";
[
["light", "亮色"],
["dark", "暗色"],
["auto", "跟随系统"]
].forEach(opt => {
let option = document.createElement("option");
option.value = opt[0];
option.innerText = opt[1];
Select.appendChild(option);
});
Select.value = localStorage.getItem("UserScript-Setting-Theme") || "auto";
Select.addEventListener("change", () => {
localStorage.setItem("UserScript-Setting-Theme", Select.value);
initTheme();
});
Row.appendChild(Select);
} else if (Data[i].Children == undefined) {
let CheckBox = document.createElement("input");
CheckBox.classList.add("form-check-input");
CheckBox.classList.add("me-1");
Expand Down Expand Up @@ -1389,7 +1460,7 @@ async function main() {
}, {"ID": "ResetType", "Type": "F", "Name": "重新排版*"}, {
"ID": "AddColorText", "Type": "A", "Name": "增加彩色文字"
}, {"ID": "AddUnits", "Type": "A", "Name": "状态界面内存与耗时添加单位"}, {
"ID": "DarkMode", "Type": "A", "Name": "使用暗色模式"
"ID": "Theme", "Type": "A", "Name": "界面主题"
}, {"ID": "AddAnimation", "Type": "A", "Name": "增加动画"}, {
"ID": "ReplaceYN", "Type": "F", "Name": "题目前状态提示替换为好看的图标"
}, {"ID": "RemoveAlerts", "Type": "D", "Name": "去除多余反复的提示"}, {
Expand Down Expand Up @@ -3213,12 +3284,11 @@ async function main() {
.then((Response) => {
return Response.text();
})
.then((Response) => {
.then(async (Response) => {
if (UtilityEnabled("LoginFailed")) {
if (Response.indexOf("history.go(-2);") != -1) {
if (UtilityEnabled("SavePassword")) {
localStorage.setItem("UserScript-Username", Username);
localStorage.setItem("UserScript-Password", Password);
await storeCredential(Username, Password);
}
let NewPage = localStorage.getItem("UserScript-LastPage");
if (NewPage == null) {
Expand All @@ -3227,8 +3297,7 @@ async function main() {
location.href = NewPage;
} else {
if (UtilityEnabled("SavePassword")) {
localStorage.removeItem("UserScript-Username");
localStorage.removeItem("UserScript-Password");
clearCredential();
}
Response = Response.substring(Response.indexOf("alert('") + 7);
Response = Response.substring(0, Response.indexOf("');"));
Expand All @@ -3244,10 +3313,15 @@ async function main() {
});
}
});
if (UtilityEnabled("SavePassword") && localStorage.getItem("UserScript-Username") != null && localStorage.getItem("UserScript-Password") != null) {
document.querySelector("#login > div:nth-child(1) > div > input").value = localStorage.getItem("UserScript-Username");
document.querySelector("#login > div:nth-child(2) > div > input").value = localStorage.getItem("UserScript-Password");
LoginButton.click();
if (UtilityEnabled("SavePassword")) {
(async () => {
let Credential = await getCredential();
if (Credential) {
document.querySelector("#login > div:nth-child(1) > div > input").value = Credential.id;
document.querySelector("#login > div:nth-child(2) > div > input").value = Credential.password;
LoginButton.click();
}
})();
}
} else if (location.pathname == "/contest_video.php" || location.pathname == "/problem_video.php") {
let ScriptData = document.querySelector("body > div > div.mt-3 > center > script").innerHTML;
Expand Down Expand Up @@ -3814,7 +3888,7 @@ int main()
AddUser.disabled = true;
RequestAPI("SendMail", {
"ToUser": String(UsernameData),
"Content": String("您好,我是" + localStorage.getItem("UserScript-Username"))
"Content": String("您好,我是" + CurrentUsername)
}, (ResponseData) => {
AddUser.children[0].style.display = "none";
AddUser.disabled = false;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "xmoj-script",
"version": "2.1.0",
"version": "2.2.0",
"description": "an improvement script for xmoj.tech",
"main": "AddonScript.js",
"scripts": {
Expand Down
Loading