Tabbed AtCoder Editorial

display atcoder editorial in tabs

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

  1. // ==UserScript==
  2. // @name Tabbed AtCoder Editorial
  3. // @version 0.1
  4. // @description display atcoder editorial in tabs
  5. // @match https://atcoder.jp/contests/*/editorial
  6. // @grant GM_addStyle
  7. // @license MIT
  8. // @namespace https://greatest.deepsurf.us/users/808669
  9. // ==/UserScript==
  10.  
  11. /* jshint esversion:8 */
  12. (async function () {
  13. 'use strict';
  14. async function addScript(src) {
  15. return new Promise((resolve) => {
  16. const script = document.createElement("script");
  17. script.type = "text/javascript";
  18. script.src = src;
  19. script.onload = resolve;
  20. document.getElementsByTagName("head")[0].appendChild(script);
  21. });
  22. }
  23.  
  24. async function addLink(href) {
  25. return new Promise((resolve) => {
  26. const link = document.createElement("link");
  27. link.rel = "stylesheet";
  28. link.href = href;
  29. link.onload = resolve;
  30. document.getElementsByTagName("head")[0].appendChild(link);
  31. });
  32. }
  33.  
  34. async function getEditorial(link) {
  35. return new Promise((resolve) => {
  36. const xhr = new XMLHttpRequest();
  37. xhr.responseType = "document";
  38. xhr.onload = (response) => {
  39. const editorial = response.target.responseXML.querySelector("#main-container > div.row > div:nth-child(2) > div:nth-child(3)");
  40. if (editorial) link.parentNode.appendChild(editorial);
  41. resolve();
  42. };
  43. xhr.open("GET", link.href);
  44. xhr.send();
  45. });
  46. }
  47.  
  48. async function getAllEditorials() {
  49. return Promise.all(Array.prototype.filter.call(document.getElementsByTagName('a'), e => e.href.match(/\/editorial\//))
  50. .map(e => getEditorial(e)));
  51. }
  52.  
  53. async function createTab() {
  54. const parser = new DOMParser();
  55. const parse = s => parser.parseFromString(s, "text/html").body.firstChild;
  56. const nav = document.querySelector("#main-container > div.row > div:nth-child(2)");
  57. const dummy = document.createElement("div");
  58. const navul = parse(`<ul class="nav nav-tabs" role="tablist"></ul>`);
  59. const navdiv = parse(`<div class="tab-content"></div>`);
  60.  
  61. let previd = "dummy";
  62. let isactive = true;
  63. let prevhead = -1;
  64. let kaisetsu = -1;
  65.  
  66. while (nav.children.length > 0) {
  67. const e = nav.firstChild;
  68. const summary = e.textContent.trimStart().split(/\s+/)[0];
  69. if (e.tagName === "DIV" && summary === "解説") {
  70. kaisetsu = dummy.children.length;
  71. dummy.appendChild(e);
  72. } else if (e.tagName === "DIV" || e.tagName === "H3") {
  73. console.log(e);
  74. const cond = e.textContent === "コンテスト全体の解説";
  75. const name = cond ? "全体" : e.textContent.trimStart().split(/\s+/)[0];
  76. const id = cond ? "all" : e.textContent.trimStart().split(/\s+/)[0];
  77. const li = parse(`<li role="presentation">
  78. <a href="#editorial-${id}" aria-controls="editorial-${id}" role="tab" data-toggle="tab">${name}</a>
  79. </li>`);
  80. if (isactive) li.classList.add("active");
  81. navul.appendChild(li);
  82. previd = id;
  83. prevhead = dummy.children.length;
  84. dummy.appendChild(e);
  85. } else if (e.tagName === "UL" || e.tagName == "P") {
  86. const div = document.createElement("div");
  87. div.role = "tabpanel";
  88. div.classList.add("tab-pane");
  89. if (isactive) div.classList.add("active");
  90. div.id = "editorial-" + previd;
  91. console.log(prevhead, dummy);
  92. div.appendChild(dummy.children[prevhead]);
  93. div.appendChild(e);
  94. navdiv.appendChild(div);
  95. isactive = false;
  96. } else {
  97. dummy.appendChild(e);
  98. }
  99. }
  100.  
  101. if (kaisetsu >= 0) nav.appendChild(dummy.children[kaisetsu]);
  102. nav.appendChild(navul);
  103. nav.appendChild(navdiv);
  104. return Promise.all(Array.prototype.filter.call(navdiv.getElementsByTagName('a'), e => e.href.match(/\/editorial\//))
  105. .map(e => getEditorial(e)));
  106. }
  107.  
  108. GM_addStyle("pre code { tab-size: 4; }");
  109. await createTab();
  110. await addLink("https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.css");
  111. await addScript("https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.js");
  112. await addScript("https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/contrib/auto-render.min.js");
  113. await addScript("https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js");
  114. renderMathInElement(document.body);
  115. })();