View all editorials of the AtCoder contest in one page.
目前為
// ==UserScript==
// @name View All Editorials
// @name:ja 解説ぜんぶ見る
// @description View all editorials of the AtCoder contest in one page.
// @description:ja AtCoderコンテストの解説ページに、すべての問題の解説をまとめて表示します。
// @version 1.3.1
// @icon https://www.google.com/s2/favicons?domain=atcoder.jp
// @match https://atcoder.jp/contests/*/editorial
// @match https://atcoder.jp/contests/*/editorial?*
// @grant GM_addStyle
// @namespace https://gitlab.com/w0mbat/user-scripts
// @author w0mbat
// ==/UserScript==
(async function () {
'use strict';
console.log(`🐻 "View All Editorials" start execution. 🐻`)
const appendHeadChild = (tagName, options) =>
Object.assign(document.head.appendChild(document.createElement(tagName)), options);
const addScript = (src) => new Promise((resolve) => {
appendHeadChild('script', { src, type: 'text/javascript', onload: resolve });
});
const addStyleSheet = (src) => new Promise((resolve) => {
appendHeadChild('link', { rel: 'stylesheet', href: src, onload: resolve });
});
const loadKaTex = async () => {
await addStyleSheet("https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css");
await addScript("https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js");
await addScript("https://cdn.jsdelivr.net/npm/[email protected]/dist/contrib/auto-render.min.js");
const kaTexOptions = {
delimiters: [
{ left: "$$", right: "$$", display: true },
{ left: "$", right: "$", display: false },
{ left: "\\(", right: "\\)", display: false },
{ left: "\\[", right: "\\]", display: true }
],
ignoredTags: ["script", "noscript", "style", "textarea", "code", "option"],
ignoredClasses: ["prettyprint", "source-code-for-copy"],
throwOnError: false
};
/* global renderMathInElement */
renderMathInElement && renderMathInElement(document.body, kaTexOptions);
};
const loadPrettifier = async () =>
await addScript("https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js");
const scrape = (doc) =>
doc.querySelector("#main-container > div.row > div:nth-child(2) > div:nth-of-type(1)");
const loadEditorial = async (link) => {
link.parentNode.classList.add('🐻-editorial-item');
const response = await fetch(link.href);
if (!response.ok) throw "Fetch failed";
const dom = scrape(new DOMParser().parseFromString(await response.text(), 'text/html'));
if (!dom) throw "Scraping failed";
link.parentNode.appendChild(dom).classList.add('🐻-editorial-content');
};
const filter4InternalEditorialLink = (link) => link.href.match(/\/contests\/.+\/editorial\//);
const loadAllEditorials = () => Promise.all(
Array.prototype.filter.call(document.getElementsByTagName('a'), filter4InternalEditorialLink)
.map(e => loadEditorial(e).catch(ex => console.warn(`🐻 Something wrong: "${e.href}", ${ex}`))));
GM_addStyle(`
pre code { tab-size: 2; }
.🐻-editorial-item { margin-bottom: 1.5em; font-size: larger; }
.🐻-editorial-content { font-size: smaller; }
`);
await loadAllEditorials();
await loadKaTex();
await loadPrettifier();
console.log(`🐻 "View All Editorials" end execution. 🐻`)
})();