﻿if (document.addEventListener) {
    document.addEventListener("DOMContentLoaded", SyntaxHighlite, false);
} else if (window.attachEvent) {
    window.attachEvent("onload", SyntaxHighlite);
}

function SyntaxHighlite() {
    TinySyntaxHighlighter.initialize();
}

var TinySyntaxHighlighter =
{
    currentStyle: "",

    /* Searches all <pre> elements in a current page and highlights the syntax */
    initialize: function () {

        // browse all <pre> elements in the page
        var preElements = document.getElementsByTagName("pre");
        for (var i = 0; i < preElements.length; i++) {

            // try highlight the syntax
            TinySyntaxHighlighter.highlightBlock(preElements[i]);
        }
    },


    /* Highlights a syntax in a given <pre> element */
    highlightBlock: function (preElement) {

        // determine the language
        var m = preElement.className.match("syntax_([a-z]+)");
        if (m != null && m.length == 2) {
            if (TinySyntaxHighlighter[preElement.className]) {
                preElement.innerHTML = TinySyntaxHighlighter.highlightSyntax(preElement.innerText || preElement.textContent, TinySyntaxHighlighter[preElement.className]);
            }
        }
    },

    /* Highlights */
    highlightSyntax: function (source, definition) {

        // initialize
        this.currentStyle = "";
        var state = definition.states[0];
        var styleName = definition.styles[0].name;
        var text = [];
        TinySyntaxHighlighter.openStyle(text, definition, state.style);

        // process the source code
        for (var i = 0; i < source.length; ) {

            // try to find a nearest applicable transition (first found wins)
            var transition = null;
            var index = -1;
            var m = null;
            var bestMatch = null;
            var rest = source.substring(i);
            for (var j in state.transitions) {
                if ((m = rest.match(state.transitions[j].expression)) != null) {
                    if (index == -1 || m.index < index) {
                        transition = state.transitions[j];
                        bestMatch = m;
                        index = m.index;
                    }
                }
            }

            // change the state if needed
            if (transition) {
                // write a prefix and a recognition sequence
                text.push(TinySyntaxHighlighter.htmlEncode(source.substring(i, i + index)));
                TinySyntaxHighlighter.openStyle(text, definition, transition.style);
                text.push(TinySyntaxHighlighter.htmlEncode(bestMatch[0]));
                i = i + index + bestMatch[0].length;

                // change the state
                state = null;
                for (var j in definition.states) {
                    if (definition.states[j].name == transition.state) {
                        state = definition.states[j];
                        break;
                    }
                }
                if (state == null)
                    throw "Invalid state name specified in a syntax definition!";

                // change the style
                TinySyntaxHighlighter.openStyle(text, definition, state.style);
            }
            else {
                // no applicable transition, enter the rest of a string
                text.push(TinySyntaxHighlighter.htmlEncode(source.substring(i)));
                i = source.length;
            }
        }

        // return the text
        TinySyntaxHighlighter.openStyle(text, definition, "");
        return text.join("");
    },

    /* Append a SPAN tag with a specified style definition */
    openStyle: function (text, definition, styleName) {

        // if there is no need to change the style, skip
        if (this.currentStyle == styleName)
            return;

        // close a style if it is open
        if (this.currentStyle != "") {
            this.currentStyle = "";
            text.push("</span>");
        }

        // find a specified style definition
        for (var i = 0; i < definition.styles.length; i++) {
            var style = definition.styles[i];
            if (style.name == styleName) {

                // append a SPAN tag
                var txt = "<span";
                if (style.style) {
                    txt = txt + " style=\"";
                    for (var j in style.style)
                        txt = txt + j.replace(/_/g, "-") + ":" + style.style[j] + ";";
                    txt = txt + "\"";
                }
                txt = txt + ">";

                this.currentStyle = styleName;
                text.push(txt);
                return;
            }
        }

        if (styleName != "")
            throw "Invalid style name specified in a syntax definition!";
    },

    htmlEncode: function (str) {
        return str.replace(/&/g, "&amo;").replace(new RegExp("\"", "g"), "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
    }
};

////////////////////////////////////////////////////////////////
//    syntax_csharp.js
////////////////////////////////////////////////////////////////

TinySyntaxHighlighter.syntax_csharp =
{
    states: [
    {
        name: "default", style: "default",
        transitions: [
        { expression: new RegExp("@\""), state: "string_ml", style: "string" },
        { expression: new RegExp("\""), state: "string", style: "string" },
        { expression: new RegExp("'"), state: "char", style: "string" },
        { expression: new RegExp("///"), state: "comment", style: "comment_xml" },
        { expression: new RegExp("//"), state: "comment", style: "comment" },
        { expression: new RegExp("/\\*"), state: "comment_ml", style: "comment" },
        { expression: new RegExp("\\b(abstract|as|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|void|volatile|while|add|dynamic|from|get|global|group|into|join|let|orderby|partial|remove|select|set|value|var|where|where|yield)\\b", "i"), state: "default", style: "keyword" }
      ]
    },
    {
        name: "comment", style: "comment",
        transitions: [
        { expression: new RegExp("<[/a-zA-Z0-9]"), state: "comment_xml", style: "comment_xml" },
        { expression: new RegExp("\\n"), state: "default", style: "comment" }
      ]
    },
    {
        name: "comment_xml", style: "comment_xml",
        transitions: [
        { expression: new RegExp(">"), state: "comment", style: "comment_xml" }
      ]
    },
    {
        name: "comment_ml", style: "comment",
        transitions: [
        { expression: new RegExp("\\*/"), state: "default", style: "comment" }
      ]
    },
    {
        name: "string_ml", style: "string",
        transitions: [
        { expression: new RegExp("\"\""), state: "string_ml", style: "string" },
        { expression: new RegExp("\""), state: "default", style: "string" }
      ]
    },
    {
        name: "string", style: "string",
        transitions: [
        { expression: new RegExp("\""), state: "default", style: "string" },
        { expression: new RegExp("\\n"), state: "default", style: "string" },
        { expression: new RegExp("\\\\\""), state: "string", style: "string" }
      ]
    },
    {
        name: "char", style: "string",
        transitions: [
        { expression: new RegExp("\\'"), state: "char", style: "string" },
        { expression: new RegExp("'"), state: "default", style: "string" }
      ]
    }
  ],
    styles: [
    {
        name: "default",
        style: { color: "black" }
    },
    {
        name: "comment",
        style: { color: "green" }
    },
    {
        name: "comment_xml",
        style: { color: "gray" }
    },
    {
        name: "string",
        style: { color: "maroon" }
    },
    {
        name: "keyword",
        style: { color: "blue" }
    }
  ]
};

////////////////////////////////////////////////////////////////
//    syntax_sql.js
////////////////////////////////////////////////////////////////

TinySyntaxHighlighter.syntax_sql =
{
    states: [
    {
        name: "default", style: "default",
        transitions: [
        { expression: new RegExp("'"), state: "string_ml", style: "string" },
        { expression: new RegExp("--"), state: "comment", style: "comment" },
        { expression: new RegExp("/\\*"), state: "comment_ml", style: "comment" },
        { expression: new RegExp("\\["), state: "identifier", style: "default" },
        { expression: new RegExp("\\b(ADD|EXCEPT|PERCENT|ALL|EXEC|PLAN|ALTER|EXECUTE|PRECISION|AND|EXISTS|PRIMARY|ANY|EXIT|PRINT|AS|FETCH|PROC|ASC|FILE|PROCEDURE|AUTHORIZATION|FILLFACTOR|PUBLIC|BACKUP|FOR|RAISERROR|BEGIN|FOREIGN|READ|BETWEEN|FREETEXT|READTEXT|BREAK|FREETEXTTABLE|RECONFIGURE|BROWSE|FROM|REFERENCES|BULK|FULL|REPLICATION|BY|FUNCTION|RESTORE|CASCADE|GOTO|RESTRICT|CASE|GRANT|RETURN|CHECK|GROUP|REVOKE|CHECKPOINT|HAVING|RIGHT|CLOSE|HOLDLOCK|ROLLBACK|CLUSTERED|IDENTITY|ROWCOUNT|COALESCE|IDENTITY_INSERT|ROWGUIDCOL|COLLATE|IDENTITYCOL|RULE|COLUMN|IF|SAVE|COMMIT|IN|SCHEMA|COMPUTE|INDEX|SELECT|CONSTRAINT|INNER|SESSION_USER|CONTAINS|INSERT|SET|CONTAINSTABLE|INTERSECT|SETUSER|CONTINUE|INTO|SHUTDOWN|CONVERT|IS|SOME|CREATE|JOIN|STATISTICS|CROSS|KEY|SYSTEM_USER|CURRENT|KILL|TABLE|CURRENT_DATE|LEFT|TEXTSIZE|CURRENT_TIME|LIKE|THEN|CURRENT_TIMESTAMP|LINENO|TO|CURRENT_USER|LOAD|TOP|CURSOR|NATIONAL|TRAN|DATABASE|NOCHECK|TRANSACTION|DBCC|NONCLUSTERED|TRIGGER|DEALLOCATE|NOT|TRUNCATE|DECLARE|NULL|TSEQUAL|DEFAULT|NULLIF|UNION|DELETE|OF|UNIQUE|DENY|OFF|UPDATE|DESC|OFFSETS|UPDATETEXT|DISK|ON|USE|DISTINCT|OPEN|USER|DISTRIBUTED|OPENDATASOURCE|VALUES|DOUBLE|OPENQUERY|VARYING|DROP|OPENROWSET|VIEW|DUMMY|OPENXML|WAITFOR|DUMP|OPTION|WHEN|ELSE|OR|WHERE|END|ORDER|WHILE|ERRLVL|OUTER|WITH|ESCAPE|OVER|WRITETEXT)\\b", "i"), state: "default", style: "keyword" }
      ]
    },
    {
        name: "identifier", style: "default",
        transitions: [
        { expression: new RegExp("\\]"), state: "default", style: "default" }
      ]
    },
    {
        name: "comment", style: "comment",
        transitions: [
        { expression: new RegExp("\\n"), state: "default", style: "comment" }
      ]
    },
    {
        name: "comment_ml", style: "comment",
        transitions: [
        { expression: new RegExp("\\*/"), state: "default", style: "comment" }
      ]
    },
    {
        name: "string_ml", style: "string",
        transitions: [
        { expression: new RegExp("''"), state: "string_ml", style: "string" },
        { expression: new RegExp("'"), state: "default", style: "string" }
      ]
    }
  ],
    styles: [
    {
        name: "default",
        style: { color: "black" }
    },
    {
        name: "comment",
        style: { color: "green" }
    },
    {
        name: "string",
        style: { color: "red" }
    },
    {
        name: "keyword",
        style: { color: "blue" }
    }
  ]
};

////////////////////////////////////////////////////////////////
//    syntax_xml.js
////////////////////////////////////////////////////////////////

TinySyntaxHighlighter.syntax_xml =
{
    states: [
    {
        name: "default", style: "default",
        transitions: [
        { expression: new RegExp("<!--"), state: "comment", style: "comment" },
        { expression: new RegExp("<!\\[CDATA\\["), state: "cdata", style: "cdata" },
        { expression: new RegExp("<%"), state: "code_block", style: "code_block" },
        { expression: new RegExp("<"), state: "elm_name", style: "brace" }
      ]
    },
    {
        name: "code_block", style: "default",
        transitions: [
        { expression: new RegExp("%>"), state: "default", style: "code_block" }
      ]
    },
    {
        name: "comment", style: "comment",
        transitions: [
        { expression: new RegExp("-->"), state: "default", style: "comment" }
      ]
    },
    {
        name: "cdata", style: "cdata",
        transitions: [
        { expression: new RegExp("\\]\\]>"), state: "default", style: "cdata" }
      ]
    },
    {
        name: "elm_name", style: "elm_name",
        transitions: [
        { expression: new RegExp("\\s*/"), state: "elm_name", style: "brace" },
        { expression: new RegExp("\\?"), state: "elm_name", style: "brace" },
        { expression: new RegExp(">"), state: "default", style: "brace" },
        { expression: new RegExp("\\s"), state: "attr_name", style: "elm_name" }
      ]
    },
    {
        name: "attr_name", style: "attr_name",
        transitions: [
        { expression: new RegExp(">"), state: "default", style: "brace" },
        { expression: new RegExp("=\\s*\""), state: "attr_value_q", style: "attr_quote" },
        { expression: new RegExp("=\\s*'"), state: "attr_value_a", style: "attr_quote" }
      ]
    },
    {
        name: "attr_value_q", style: "attr_value",
        transitions: [
        { expression: new RegExp("\""), state: "elm_name", style: "attr_quote" }
      ]
    },
    {
        name: "attr_value_a", style: "attr_value",
        transitions: [
        { expression: new RegExp("'"), state: "elm_name", style: "attr_quote" }
      ]
    }
  ],
    styles: [
    {
        name: "default",
        style: { color: "black" }
    },
    {
        name: "comment",
        style: { color: "green" }
    },
    {
        name: "cdata",
        style: { color: "gray" }
    },
    {
        name: "brace",
        style: { color: "blue" }
    },
    {
        name: "elm_name",
        style: { color: "maroon" }
    },
    {
        name: "attr_name",
        style: { color: "red" }
    },
    {
        name: "attr_value",
        style: { color: "blue" }
    },
    {
        name: "attr_quote",
        style: { color: "black" }
    },
    {
        name: "code_block",
        style: { color: "black", background_color: "yellow" }
    }
  ]
};

////////////////////////////////////////////////////////////////
//    syntax_js.js
////////////////////////////////////////////////////////////////

TinySyntaxHighlighter.syntax_js =
{
    states: [
    {
        name: "default", style: "default",
        transitions: [
        { expression: new RegExp("\""), state: "string", style: "string" },
        { expression: new RegExp("'"), state: "string", style: "string" },
        { expression: new RegExp("//"), state: "comment", style: "comment" },
        { expression: new RegExp("/\\*"), state: "comment_ml", style: "comment" },
        { expression: new RegExp("\\b(var|function|true|false|for|if|else|break|continue|switch|case)\\b", "i"), state: "default", style: "keyword" }
      ]
    },
    {
        name: "string", style: "string",
        transitions: [
        { expression: new RegExp("\""), state: "default", style: "string" },
        { expression: new RegExp("'"), state: "default", style: "string" },
      ]
    },
    {
        name: "comment", style: "comment",
        transitions: [
        { expression: new RegExp("\\n"), state: "default", style: "comment" }
      ]
    },
    {
        name: "comment_ml", style: "comment",
        transitions: [
        { expression: new RegExp("\\*/"), state: "default", style: "comment" }
      ]
    }
  ],
    styles: [
    {
        name: "default",
        style: { color: "black" }
    },
    {
        name: "comment",
        style: { color: "green" }
    },
    {
        name: "string",
        style: { color: "maroon" }
    },
    {
        name: "keyword",
        style: { color: "blue" }
    }
  ]
};