Go.dev Golang Website Code Highlight

Golang code highlighter

Från och med 2023-12-20. Se den senaste versionen.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Go.dev Golang Website Code Highlight
// @version      1.1.7
// @description  Golang code highlighter
// @author       Anton Vi
// @match        https://*.go.dev/*

// @resource     IMPORTED_CSS  https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css

// @grant        GM_getResourceText
// @grant        GM_addStyle
// @license      GNU GPLv3

// @exclude      https://go.dev/tour/*
// @exclude      https://go.dev/solutions/*
// @exclude      https://go.dev/security/*
// @namespace GolangDevNamespace
// ==/UserScript==

(function() {

    'use strict';

    document.addEventListener('readystatechange', (e) => {
        if (e.target.readyState === 'complete') {
            resetBlogCss();
            start();
        }
    })


})();

function resetBlogCss() {
    // reset styles for go dev blog
    let css = `#blog pre, #content .code, #content .playground {
        background: black; 
        font-family: Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;
        font-size: 1rem;
    }`;
    GM_addStyle(css);

}

function start() {
    // create Prisma object
    window.Prism = window.Prism || {};
    // no highlight on auto
    Prism.manual = true;

    // add highlight styles css
    const my_css = GM_getResourceText("IMPORTED_CSS");
    GM_addStyle(my_css);


    // loop pre-s and add code child elements for highlight
    let pre_s = document.getElementsByTagName('pre');
    for (let el of pre_s) {
        // skip pre element for ==Output== code run in documentation
        if (el.getElementsByClassName('Documentation-exampleOutputLabel').length > 0) {
            continue;
        }

        el.className = 'language-go';


        if (!el.getElementsByTagName('code').length > 0) {
            let text = el.innerHTML;
            el.innerHTML = '';

            let code = document.createElement('code');
            code.innerHTML = text;
            code.className = 'language-go';
            el.appendChild(code);
        }

    }


    // get examples in go library doc
    let divS = document.getElementsByClassName('Documentation-exampleDetailsBody');
    for (divEl of divS) {
        let outputPre = divEl.getElementsByTagName('pre')[0];
        outputPre.className = 'language-go';


        let textareaBlock = divEl.querySelector('textarea.Documentation-exampleCode.code');
        textareaBlock.style.display = 'none';
        // textareaBlock.remove();
        divEl.insertAdjacentHTML('afterbegin', '<pre class="language-go"><code>' + textareaBlock.value + '</code></pre>');


    }


    // start prism
    initPrismCore();

    // add languages syntax
    addClikeSyntax();
    addGoSyntax();


    // start highlight syntax
    Prism.highlightAll();

}

function initPrismCore() {
    var _self = "undefined" != typeof window ? window : "undefined" != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope ? self : {},
        Prism = function(e) {
            var n = /(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,
                t = 0,
                r = {},
                a = {
                    manual: e.Prism && e.Prism.manual,
                    disableWorkerMessageHandler: e.Prism && e.Prism.disableWorkerMessageHandler,
                    util: {
                        encode: function e(n) { return n instanceof i ? new i(n.type, e(n.content), n.alias) : Array.isArray(n) ? n.map(e) : n.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/\u00a0/g, " ") },
                        type: function(e) { return Object.prototype.toString.call(e).slice(8, -1) },
                        objId: function(e) { return e.__id || Object.defineProperty(e, "__id", { value: ++t }), e.__id },
                        clone: function e(n, t) {
                            var r, i;
                            switch (t = t || {}, a.util.type(n)) {
                                case "Object":
                                    if (i = a.util.objId(n), t[i]) return t[i];
                                    for (var l in r = {}, t[i] = r, n) n.hasOwnProperty(l) && (r[l] = e(n[l], t));
                                    return r;
                                case "Array":
                                    return i = a.util.objId(n), t[i] ? t[i] : (r = [], t[i] = r, n.forEach((function(n, a) { r[a] = e(n, t) })), r);
                                default:
                                    return n
                            }
                        },
                        getLanguage: function(e) {
                            for (; e;) {
                                var t = n.exec(e.className);
                                if (t) return t[1].toLowerCase();
                                e = e.parentElement
                            }
                            return "none"
                        },
                        setLanguage: function(e, t) { e.className = e.className.replace(RegExp(n, "gi"), ""), e.classList.add("language-" + t) },
                        currentScript: function() {
                            if ("undefined" == typeof document) return null;
                            if ("currentScript" in document) return document.currentScript;
                            try { throw new Error } catch (r) {
                                var e = (/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(r.stack) || [])[1];
                                if (e) {
                                    var n = document.getElementsByTagName("script");
                                    for (var t in n)
                                        if (n[t].src == e) return n[t]
                                }
                                return null
                            }
                        },
                        isActive: function(e, n, t) {
                            for (var r = "no-" + n; e;) {
                                var a = e.classList;
                                if (a.contains(n)) return !0;
                                if (a.contains(r)) return !1;
                                e = e.parentElement
                            }
                            return !!t
                        }
                    },
                    languages: {
                        plain: r,
                        plaintext: r,
                        text: r,
                        txt: r,
                        extend: function(e, n) { var t = a.util.clone(a.languages[e]); for (var r in n) t[r] = n[r]; return t },
                        insertBefore: function(e, n, t, r) {
                            var i = (r = r || a.languages)[e],
                                l = {};
                            for (var o in i)
                                if (i.hasOwnProperty(o)) {
                                    if (o == n)
                                        for (var s in t) t.hasOwnProperty(s) && (l[s] = t[s]);
                                    t.hasOwnProperty(o) || (l[o] = i[o])
                                } var u = r[e];
                            return r[e] = l, a.languages.DFS(a.languages, (function(n, t) { t === u && n != e && (this[n] = l) })), l
                        },
                        DFS: function e(n, t, r, i) {
                            i = i || {};
                            var l = a.util.objId;
                            for (var o in n)
                                if (n.hasOwnProperty(o)) {
                                    t.call(n, o, n[o], r || o);
                                    var s = n[o],
                                        u = a.util.type(s);
                                    "Object" !== u || i[l(s)] ? "Array" !== u || i[l(s)] || (i[l(s)] = !0, e(s, t, o, i)) : (i[l(s)] = !0, e(s, t, null, i))
                                }
                        }
                    },
                    plugins: {},
                    highlightAll: function(e, n) { a.highlightAllUnder(document, e, n) },
                    highlightAllUnder: function(e, n, t) {
                        var r = { callback: t, container: e, selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code' };
                        a.hooks.run("before-highlightall", r), r.elements = Array.prototype.slice.apply(r.container.querySelectorAll(r.selector)), a.hooks.run("before-all-elements-highlight", r);
                        for (var i, l = 0; i = r.elements[l++];) a.highlightElement(i, !0 === n, r.callback)
                    },
                    highlightElement: function(n, t, r) {
                        var i = a.util.getLanguage(n),
                            l = a.languages[i];
                        a.util.setLanguage(n, i);
                        var o = n.parentElement;
                        o && "pre" === o.nodeName.toLowerCase() && a.util.setLanguage(o, i);
                        var s = { element: n, language: i, grammar: l, code: n.textContent };

                        function u(e) { s.highlightedCode = e, a.hooks.run("before-insert", s), s.element.innerHTML = s.highlightedCode, a.hooks.run("after-highlight", s), a.hooks.run("complete", s), r && r.call(s.element) }
                        if (a.hooks.run("before-sanity-check", s), (o = s.element.parentElement) && "pre" === o.nodeName.toLowerCase() && !o.hasAttribute("tabindex") && o.setAttribute("tabindex", "0"), !s.code) return a.hooks.run("complete", s), void(r && r.call(s.element));
                        if (a.hooks.run("before-highlight", s), s.grammar)
                            if (t && e.Worker) {
                                var c = new Worker(a.filename);
                                c.onmessage = function(e) { u(e.data) }, c.postMessage(JSON.stringify({ language: s.language, code: s.code, immediateClose: !0 }))
                            } else u(a.highlight(s.code, s.grammar, s.language));
                        else u(a.util.encode(s.code))
                    },
                    highlight: function(e, n, t) { var r = { code: e, grammar: n, language: t }; if (a.hooks.run("before-tokenize", r), !r.grammar) throw new Error('The language "' + r.language + '" has no grammar.'); return r.tokens = a.tokenize(r.code, r.grammar), a.hooks.run("after-tokenize", r), i.stringify(a.util.encode(r.tokens), r.language) },
                    tokenize: function(e, n) {
                        var t = n.rest;
                        if (t) {
                            for (var r in t) n[r] = t[r];
                            delete n.rest
                        }
                        var a = new s;
                        return u(a, a.head, e), o(e, a, n, a.head, 0),
                            function(e) { for (var n = [], t = e.head.next; t !== e.tail;) n.push(t.value), t = t.next; return n }(a)
                    },
                    hooks: {
                        all: {},
                        add: function(e, n) {
                            var t = a.hooks.all;
                            t[e] = t[e] || [], t[e].push(n)
                        },
                        run: function(e, n) {
                            var t = a.hooks.all[e];
                            if (t && t.length)
                                for (var r, i = 0; r = t[i++];) r(n)
                        }
                    },
                    Token: i
                };

            function i(e, n, t, r) { this.type = e, this.content = n, this.alias = t, this.length = 0 | (r || "").length }

            function l(e, n, t, r) {
                e.lastIndex = n;
                var a = e.exec(t);
                if (a && r && a[1]) {
                    var i = a[1].length;
                    a.index += i, a[0] = a[0].slice(i)
                }
                return a
            }

            function o(e, n, t, r, s, g) {
                for (var f in t)
                    if (t.hasOwnProperty(f) && t[f]) {
                        var h = t[f];
                        h = Array.isArray(h) ? h : [h];
                        for (var d = 0; d < h.length; ++d) {
                            if (g && g.cause == f + "," + d) return;
                            var v = h[d],
                                p = v.inside,
                                m = !!v.lookbehind,
                                y = !!v.greedy,
                                k = v.alias;
                            if (y && !v.pattern.global) {
                                var x = v.pattern.toString().match(/[imsuy]*$/)[0];
                                v.pattern = RegExp(v.pattern.source, x + "g")
                            }
                            for (var b = v.pattern || v, w = r.next, A = s; w !== n.tail && !(g && A >= g.reach); A += w.value.length, w = w.next) {
                                var E = w.value;
                                if (n.length > e.length) return;
                                if (!(E instanceof i)) {
                                    var P, L = 1;
                                    if (y) {
                                        if (!(P = l(b, A, e, m)) || P.index >= e.length) break;
                                        var S = P.index,
                                            O = P.index + P[0].length,
                                            j = A;
                                        for (j += w.value.length; S >= j;) j += (w = w.next).value.length;
                                        if (A = j -= w.value.length, w.value instanceof i) continue;
                                        for (var C = w; C !== n.tail && (j < O || "string" == typeof C.value); C = C.next) L++, j += C.value.length;
                                        L--, E = e.slice(A, j), P.index -= A
                                    } else if (!(P = l(b, 0, E, m))) continue;
                                    S = P.index;
                                    var N = P[0],
                                        _ = E.slice(0, S),
                                        M = E.slice(S + N.length),
                                        W = A + E.length;
                                    g && W > g.reach && (g.reach = W);
                                    var z = w.prev;
                                    if (_ && (z = u(n, z, _), A += _.length), c(n, z, L), w = u(n, z, new i(f, p ? a.tokenize(N, p) : N, k, N)), M && u(n, w, M), L > 1) {
                                        var I = { cause: f + "," + d, reach: W };
                                        o(e, n, t, w.prev, A, I), g && I.reach > g.reach && (g.reach = I.reach)
                                    }
                                }
                            }
                        }
                    }
            }

            function s() {
                var e = { value: null, prev: null, next: null },
                    n = { value: null, prev: e, next: null };
                e.next = n, this.head = e, this.tail = n, this.length = 0
            }

            function u(e, n, t) {
                var r = n.next,
                    a = { value: t, prev: n, next: r };
                return n.next = a, r.prev = a, e.length++, a
            }

            function c(e, n, t) {
                for (var r = n.next, a = 0; a < t && r !== e.tail; a++) r = r.next;
                n.next = r, r.prev = n, e.length -= a
            }
            if (e.Prism = a, i.stringify = function e(n, t) {
                    if ("string" == typeof n) return n;
                    if (Array.isArray(n)) { var r = ""; return n.forEach((function(n) { r += e(n, t) })), r }
                    var i = { type: n.type, content: e(n.content, t), tag: "span", classes: ["token", n.type], attributes: {}, language: t },
                        l = n.alias;
                    l && (Array.isArray(l) ? Array.prototype.push.apply(i.classes, l) : i.classes.push(l)), a.hooks.run("wrap", i);
                    var o = "";
                    for (var s in i.attributes) o += " " + s + '="' + (i.attributes[s] || "").replace(/"/g, "&quot;") + '"';
                    return "<" + i.tag + ' class="' + i.classes.join(" ") + '"' + o + ">" + i.content + "</" + i.tag + ">"
                }, !e.document) return e.addEventListener ? (a.disableWorkerMessageHandler || e.addEventListener("message", (function(n) {
                var t = JSON.parse(n.data),
                    r = t.language,
                    i = t.code,
                    l = t.immediateClose;
                e.postMessage(a.highlight(i, a.languages[r], r)), l && e.close()
            }), !1), a) : a;
            var g = a.util.currentScript();

            function f() { a.manual || a.highlightAll() }
            if (g && (a.filename = g.src, g.hasAttribute("data-manual") && (a.manual = !0)), !a.manual) { var h = document.readyState; "loading" === h || "interactive" === h && g && g.defer ? document.addEventListener("DOMContentLoaded", f) : window.requestAnimationFrame ? window.requestAnimationFrame(f) : window.setTimeout(f, 16) }
            return a
        }(_self);
    "undefined" != typeof module && module.exports && (module.exports = Prism), "undefined" != typeof global && (global.Prism = Prism);
}

function addClikeSyntax() {
    Prism.languages.clike = {
        comment: [{ pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/, lookbehind: !0, greedy: !0 },
            { pattern: /(^|[^\\:])\/\/.*/, lookbehind: !0, greedy: !0 }
        ],
        string: { pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, greedy: !0 },
        "class-name": { pattern: /(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i, lookbehind: !0, inside: { punctuation: /[.\\]/ } },
        keyword: /\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,
        boolean: /\b(?:false|true)\b/,
        function: /\b\w+(?=\()/,
        number: /\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,
        operator: /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,
        punctuation: /[{}[\];(),.:]/
    };
}

function addGoSyntax() {
    Prism.languages.go = Prism.languages
        .extend("clike", {
            string: { pattern: /(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/, lookbehind: !0, greedy: !0 },
            keyword: /\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,
            boolean: /\b(?:_|false|iota|nil|true)\b/,
            number: [/\b0(?:b[01_]+|o[0-7_]+)i?\b/i, /\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i, /(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],
            operator: /[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,
            builtin: /\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/
        }),
        Prism.languages.insertBefore("go", "string", { char: { pattern: /'(?:\\.|[^'\\\r\n]){0,10}'/, greedy: !0 } }), delete Prism.languages.go["class-name"];
}