您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add a drop-down list next to the editorial buttons on AtCoder problem pages.
// ==UserScript== // @name Editorials Dropdown for AtCoder // @name:ja Editorials Dropdown for AtCoder // @namespace https://github.com/roumcha/browser-extensions/tree/main/src/editorials-dropdown-for-atcoder // @version 1.1.0 // @description Add a drop-down list next to the editorial buttons on AtCoder problem pages. // @description:ja AtCoder の解説ボタンの横にドロップダウンリストを追加します。 // @author Roumcha // @license Creative Commons Zero v1.0 Universal // @match https://atcoder.jp/contests/*/tasks/* // @grant GM.xmlHttpRequest // @connect atcoder.jp // @run-at document-end // ==/UserScript== "use strict"; (() => { // src/editorials-dropdown-for-atcoder/editorials-dropdown.ts async function editorialsDropdown({ fetchXMLDocument }) { const started = Date.now(); let lang = getLanguage(); const link = findEditorialsButton(document); if (link) { console.log("[EDFA] Found the target button: ", link); } else { console.log(`[EDFA] Editorials button not found.`); return; } const url2 = new URL(link.href); url2.searchParams.set("editorialLang", lang); const editorialsPageDoc = await fetchXMLDocument( url2 ).catch((reason) => { console.error(`[EDFA] Failed to fetch ${link.href}: ${reason}`); return null; }); if (editorialsPageDoc) { console.log(`[EDFA] Downloaded ${link.href}.`); } else { console.error(`[EDFA] ${link.href} is empty or not an XML document.`); return; } const content = createDropdownContent(editorialsPageDoc); if (content.length === 0) { console.error(`[EDFA] failed to generate the dropdown content.`); return; } const insertedElem = createDropdownAndButton(...content); link.after(insertedElem); console.log( `[EDFA] Successfully generated and inserted a drop-down list: `, insertedElem ); console.log(`[EDFA] done in ${Date.now() - started} ms.`); } var translation = { editorial: { ja: "\u89E3\u8AAC", en: "editorial" }, overallEditorial: { ja: "\u30B3\u30F3\u30C6\u30B9\u30C8\u5168\u4F53\u306E\u89E3\u8AAC", en: "overall editorial" } }; function getLanguage() { const param = new URLSearchParams(location.search).get( "lang" ); if (param) { console.log(`[EDFA] Found language '${param}' in the URL parameter.`); return param; } const cookie = document.cookie.split("; ").find((s) => s.startsWith("language="))?.split("=").at(1); if (cookie) { console.log(`[EDFA] Found language '${cookie}' in Cookie.`); return cookie; } const browser = navigator.language; if (browser == "ja") { console.log(`[EDFA] Loaded language '${browser}' from the browser.`); return "ja"; } console.log(`[EDFA] Fall back to English.`); return "en"; } function findEditorialsButton(root) { const res = [...root.querySelectorAll("a.btn")].filter( ({ textContent }) => textContent && Object.values(translation["editorial"]).includes( textContent.toLowerCase() ) ).at(0); return res; } function createDropdownContent(editorialsPageDoc) { const res = [ ...editorialsPageDoc.querySelectorAll( "#main-container > div > div:not(#contest-nav-tabs) > *" ) ].filter( ({ tagName }) => ["ul", "h3", "p"].includes(tagName.toLowerCase()) ); if (res.length === 0) { console.error(`[EDFA] failed to find editorial lists.`); } return res; } function createDropdownAndButton(...content) { const res = document.createElement("span"); res.className = "edfa-root"; res.style.position = "relative"; res.addEventListener("blur", () => res.classList.remove("open")); { const button = document.createElement("button"); button.className = "edfa-button btn btn-default btn-sm"; button.type = "button"; button.title = "open editorials list"; button.onclick = () => res.classList.toggle("open"); res.append(button); { const caret = document.createElement("span"); caret.classList.add("caret"); button.append(caret); } } { const dropdown = document.createElement("div"); dropdown.className = "edfa-dropdown dropdown-menu"; dropdown.style.position = "absolute"; dropdown.style.width = "200px"; dropdown.style.padding = "8px"; dropdown.style.zIndex = "998"; dropdown.append(...content); res.append(dropdown); } return res; } // src/editorials-dropdown-for-atcoder/info.ts var title = "Editorials Dropdown for AtCoder"; var version = "1.1.0"; var url = "https://github.com/roumcha/browser-extensions/tree/main/src/editorials-dropdown-for-atcoder"; var author = "Roumcha"; var userScriptHeader = `// ==UserScript== // @name ${title} // @name:ja ${title} // @namespace ${url} // @version ${version} // @description Add a drop-down list next to the editorial buttons on AtCoder problem pages. // @description:ja AtCoder \u306E\u89E3\u8AAC\u30DC\u30BF\u30F3\u306E\u6A2A\u306B\u30C9\u30ED\u30C3\u30D7\u30C0\u30A6\u30F3\u30EA\u30B9\u30C8\u3092\u8FFD\u52A0\u3057\u307E\u3059\u3002 // @author ${author} // @license Creative Commons Zero v1.0 Universal // @match https://atcoder.jp/contests/*/tasks/* // @grant GM.xmlHttpRequest // @connect atcoder.jp // @run-at document-end // ==/UserScript== `; // src/editorials-dropdown-for-atcoder/user-script.ts (async function() { console.log(`[EDFA] ${title} v${version} (UserScript) started.`); await editorialsDropdown({ fetchXMLDocument: async (url2) => await GM.xmlHttpRequest({ url: url2 }).then((res) => res.responseXML) }); })(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址