View All Editorials

View all editorials of the AtCoder contest in one page.

2022-10-16 या दिनांकाला. सर्वात नवीन आवृत्ती पाहा.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey, Greasemonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्क्रिप्ट व्यवस्थापक एक्स्टेंशन इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्क्रिप्ट व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्टाईल व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

// ==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. 🐻`)
})();