AtCoder Better Highlighter

Better syntax highlighting for AtCoder using highlight.js.

Від 10.10.2020. Дивіться остання версія.

// ==UserScript==
// @name         AtCoder Better Highlighter
// @namespace    https://shouth.net/
// @version      0.2
// @description  Better syntax highlighting for AtCoder using highlight.js.
// @author       shouth
// @resource     css https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.2/styles/default.min.css
// @require      https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.2/highlight.min.js
// @include      /^https:\/\/atcoder\.jp\/contests\/[^\/]+\/submissions\/[0-9]+
// @grant        GM_addStyle
// @grant        GM_getResourceText
// ==/UserScript==

(() => {
    'use strict';
    const getHighlightName = (str) => {
        switch (str) {
            case "Ada2012 (GNAT 9.2.1)": return "ada";
            case "Awk (GNU Awk 4.1.4)": return "awk";
            case "Bash (5.0.11)": return "bash";
            case "Brainfuck (bf 20041219)": return "brainfuck";
            case "C (Clang 10.0.0)": return "c";
            case "C (GCC 9.2.1)": return "c";
            case "C# (.NET Core 3.1.201)": return "csharp";
            case "C# (Mono-csc 3.5.0)": return "csharp";
            case "C# (Mono-mcs 6.8.0.105)": return "csharp";
            case "C++ (Clang 10.0.0)": return "cpp";
            case "C++ (GCC 9.2.1)": return "cpp";
            case "COBOL - Fixed (OpenCOBOL 1.1.0)": return "";
            case "COBOL - Free (OpenCOBOL 1.1.0)": return "";
            case "Clojure (1.10.1.536)": return "clojure";
            case "Common Lisp (SBCL 2.0.3)": return "lisp";
            case "Crystal (0.33.0)": return "crystal";
            case "Cython (0.29.16)": return "python";
            case "D (DMD 2.091.0)": return "d";
            case "D (GDC 9.2.1)": return "d";
            case "D (LDC 1.20.1)": return "d";
            case "Dart (2.7.2)": return "dart";
            case "Dash (0.5.8)": return "";
            case "Elixir (1.10.2)": return "elixir";
            case "Erlang (22.3)": return "erlang";
            case "F# (.NET Core 3.1.201)": return "fsharp";
            case "F# (Mono 10.2.3)": return "fsharp";
            case "Forth (gforth 0.7.3)": return "";
            case "Fortran (GNU Fortran 9.2.1)": return "fortran";
            case "Go (1.14.1)": return "go";
            case "Haskell (GHC 8.8.3)": return "haskell";
            case "Haxe (4.0.3); Java": return "haxe";
            case "Haxe (4.0.3); js": return "haxe";
            case "Java (OpenJDK 1.8.0)": return "java";
            case "Java (OpenJDK 11.0.6)": return "java";
            case "JavaScript (Node.js 12.16.1)": return "javascript";
            case "Julia (1.4.0)": return "julia";
            case "Kotlin (1.3.71)": return "kotlin";
            case "Lua (Lua 5.3.5)": return "lua";
            case "Lua (LuaJIT 2.1.0)": return "lua";
            case "Nim (1.0.6)": return "nimrod";
            case "OCaml (4.10.0)": return "ocaml";
            case "Objective-C (Clang 10.0.0)": return "objectivec";
            case "Octave (5.2.0)": return "";
            case "PHP (7.4.4)": return "php";
            case "Pascal (FPC 3.0.4)": return "pascal";
            case "Perl (5.26.1)": return "perl";
            case "Prolog (SWI-Prolog 8.0.3)": return "prolog";
            case "PyPy2 (7.3.0)": return "python";
            case "PyPy3 (7.3.0)": return "python";
            case "Python (3.8.2)": return "python";
            case "Racket (7.6)": return "";
            case "Raku (Rakudo 2020.02.1)": return "";
            case "Ruby (2.7.1)": return "ruby";
            case "Rust (1.42.0)": return "rust";
            case "Scala (2.13.1)": return "scala";
            case "Scheme (Gauche 0.9.9)": return "scheme";
            case "Sed (4.4)": return "";
            case "Standard ML (MLton 20130715)": return "sml";
            case "Swift (5.2.1)": return "swift";
            case "Text (cat 8.28)": return "";
            case "TypeScript (3.8)": return "typescript";
            case "Unlambda (2.0.0)": return "";
            case "Vim (8.2.0460)": return "vim";
            case "Visual Basic (.NET Core 3.1.101)": return "vbnet";
            case "Zsh (5.4.2)": return "";
            case "bc (1.07.1)": return "";
            case "dc (1.4.1)": return "";
            default: return "";
        }
    };

    const lang = Array.from(document.querySelectorAll("tr"))
        .find(e => [ "言語", "Languages" ].includes(e.children[0]?.textContent));
    const name = getHighlightName(lang?.children[1]?.textContent);
    if (!name) return;

    GM_addStyle(GM_getResourceText("css"));
    const style = document.createElement("style");
    style.textContent = `
        .submission-code {
            padding: 0 !important;
        }

        .line-number {
            padding: 0 10px;
            width: 50px;
            text-align: right;
        }

        .line-number::before {
            opacity: 0.3;
            content: attr(data-line-number);
        }

        .line {
            padding: 0 10px;
        }

        .lines {
            width: 100%;
        }
    `
    document.head.append(style);

    const original = document.querySelector("#for_copy0").textContent;
    const lines = hljs.highlightAuto(original).value.split("\n");
    const code = lines.map((e, i) =>
        `<tr>
             <td class="line-number" data-line-number=${i + 1}></td>
             <td class="line">${e}</td>
         </tr>`)
        .join("\n");

    const pre = document.createElement("pre");
    pre.id = "submission-code";
    pre.className = "submission-code";
    pre.innerHTML = `<table class="hljs lines"><tbody>${code}<tbody></table>`

    const sub = document.querySelector("#submission-code");
    sub.parentNode.replaceChild(pre, sub);
})();