
(function () {
    var KLYN_KEYWORDS = {
        "true": 1, "false": 1, "null": 1, "as": 1, "def": 1, "pass": 1,
        "ref": 1, "out": 1, "notnull": 1, "const": 1,
        "or": 1, "and": 1, "not": 1, "ornull": 1, "is": 1, "lambda": 1,
        "import": 1, "class": 1, "interface": 1, "enum": 1, "annotation": 1,
        "extends": 1, "implements": 1, "final": 1, "static": 1, "native": 1, "abstract": 1,
        "public": 1, "protected": 1, "private": 1, "package": 1, "override": 1, "readonly": 1, "writeonly": 1, "delegate": 1,
        "operator": 1, "property": 1, "signal": 1, "event": 1, "get": 1, "set": 1, "this": 1, "super": 1,
        "if": 1, "elif": 1, "else": 1, "match": 1, "case": 1, "default": 1,
        "for": 1, "to": 1, "step": 1, "in": 1, "while": 1, "do": 1, "until": 1, "break": 1, "continue": 1,
        "assert": 1, "return": 1, "try": 1, "catch": 1, "finally": 1, "throws": 1, "throw": 1, "emit": 1
    };

    function esc(text) {
        return text
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;");
    }

    function escAttr(text) {
        return esc(text).replace(/"/g, "&quot;");
    }

    function isIdStartCode(code) {
        return (code >= 65 && code <= 90) || (code >= 97 && code <= 122) || code === 95;
    }

    function isIdPartCode(code) {
        return isIdStartCode(code) || (code >= 48 && code <= 57) || code === 46 || code === 36;
    }

    function isDigitCode(code) {
        return code >= 48 && code <= 57;
    }

    function isHexCode(code) {
        return isDigitCode(code) || (code >= 65 && code <= 70) || (code >= 97 && code <= 102);
    }

    function isNumPartCode(code) {
        if (isHexCode(code)) return true;
        if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) return true;
        return code === 46 || code === 95;
    }

    function token(cls, value) {
        return '<span class="' + cls + '">' + esc(value) + '</span>';
    }

    function linkedToken(cls, value, href, prefix) {
        return '<a class="' + cls + '" href="' + escAttr(prefix || "") + escAttr(href) + '">' + esc(value) + '</a>';
    }

    function linkifyTypes(code, prefix) {
        var links = (typeof KLYNDOC_TYPE_LINKS === "object" && KLYNDOC_TYPE_LINKS) ? KLYNDOC_TYPE_LINKS : {};
        var i = 0;
        var n = code.length;
        var out = "";
        while (i < n) {
            var cc = code.charCodeAt(i);
            if (isIdStartCode(cc)) {
                var s = i;
                i++;
                while (i < n && isIdPartCode(code.charCodeAt(i))) i++;
                var ident = code.slice(s, i);
                var href = links[ident];
                if (href) {
                    out += '<a href="' + escAttr(prefix || "") + escAttr(href) + '">' + esc(ident) + '</a>';
                } else {
                    out += esc(ident);
                }
                continue;
            }
            out += esc(code[i]);
            i++;
        }
        return out;
    }

    function highlightKlyn(code, prefix) {
        var links = (typeof KLYNDOC_TYPE_LINKS === "object" && KLYNDOC_TYPE_LINKS) ? KLYNDOC_TYPE_LINKS : {};
        var i = 0;
        var n = code.length;
        var out = "";
        while (i < n) {
            var ch = code[i];
            var cc = code.charCodeAt(i);

            if (ch === "#") {
                var s = i;
                while (i < n && code.charCodeAt(i) !== 10) i++;
                out += token("tok-cmt", code.slice(s, i));
                continue;
            }

            if (ch === "/" && i + 1 < n && code[i + 1] === "*") {
                var b = i;
                i += 2;
                while (i + 1 < n && !(code[i] === "*" && code[i + 1] === "/")) i++;
                if (i + 1 < n) i += 2;
                out += token("tok-cmt", code.slice(b, i));
                continue;
            }

            if (cc === 34 || cc === 39) {
                var quote = cc;
                var t = i;
                var triple = (i + 2 < n && code.charCodeAt(i + 1) === quote && code.charCodeAt(i + 2) === quote);
                if (triple) i += 3;
                else i++;
                while (i < n) {
                    var ci = code.charCodeAt(i);
                    if (!triple && ci === 92) {
                        i += 2;
                        continue;
                    }
                    if (!triple && ci === quote) {
                        i++;
                        break;
                    }
                    if (triple && i + 2 < n && code.charCodeAt(i) === quote && code.charCodeAt(i + 1) === quote && code.charCodeAt(i + 2) === quote) {
                        i += 3;
                        break;
                    }
                    i++;
                }
                out += token("tok-str", code.slice(t, i));
                continue;
            }

            if (ch === "@") {
                var a = i;
                i++;
                while (i < n && isIdPartCode(code.charCodeAt(i))) i++;
                out += token("tok-ann", code.slice(a, i));
                continue;
            }

            if (isDigitCode(cc)) {
                var num = i;
                i++;
                while (i < n && isNumPartCode(code.charCodeAt(i))) i++;
                out += token("tok-num", code.slice(num, i));
                continue;
            }

            if (isIdStartCode(cc)) {
                var s2 = i;
                i++;
                while (i < n && isIdPartCode(code.charCodeAt(i))) i++;
                var ident = code.slice(s2, i);
                if (KLYN_KEYWORDS[ident]) {
                    out += token("tok-kw", ident);
                } else if (ident.length > 0 && ident[0] === ident[0].toUpperCase()) {
                    var href = links[ident];
                    if (href && prefix !== null && prefix !== undefined) {
                        out += linkedToken("tok-type", ident, href, prefix);
                    } else {
                        out += token("tok-type", ident);
                    }
                } else {
                    out += esc(ident);
                }
                continue;
            }

            if (":=+-*/<>!%&|^~?.(),[]{}".indexOf(ch) >= 0) {
                out += token("tok-op", ch);
                i++;
                continue;
            }

            out += esc(ch);
            i++;
        }
        return out;
    }

    function shouldHighlight(pre) {
        var lang = (pre.getAttribute("data-lang") || "").toLowerCase();
        return lang === "" || lang === "klyn" || lang === "kn";
    }

    function highlightAll() {
        var blocks = document.querySelectorAll("pre.code");
        for (var i = 0; i < blocks.length; i++) {
            var pre = blocks[i];
            if (pre.getAttribute("data-hl") === "1") continue;
            var linkified = pre.classList.contains("linkified");
            if (!shouldHighlight(pre)) {
                if (linkified) {
                    pre.innerHTML = linkifyTypes(pre.textContent || "", pre.getAttribute("data-prefix") || "");
                    pre.setAttribute("data-hl", "1");
                }
                continue;
            }
            pre.innerHTML = highlightKlyn(pre.textContent || "", linkified ? (pre.getAttribute("data-prefix") || "") : null);
            pre.setAttribute("data-hl", "1");
        }
    }

    if (document.readyState === "loading") {
        document.addEventListener("DOMContentLoaded", highlightAll);
    } else {
        highlightAll();
    }
})();