Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support MDX syntax highlighting in Debug modal #16

Open
jazzido opened this issue Nov 17, 2017 · 0 comments
Open

Support MDX syntax highlighting in Debug modal #16

jazzido opened this issue Nov 17, 2017 · 0 comments

Comments

@jazzido
Copy link
Contributor

jazzido commented Nov 17, 2017

Write a react-syntax-highlighter mode for MDX. Build on this:

// Adapted from Pivot4J:
// https://github.com/mysticfall/pivot4j/blob/33aa47129f02ce6eb1638ce5464e701ecf7e64d7/pivot4j-analytics/src/main/webapp/resources/pivot4j/js/codemirror-mode.js
var mdxMode = function(config, parserConfig) {
    var keywords = parserConfig.keywords, functions = parserConfig.functions, properties = parserConfig.properties, multiLineStrings = parserConfig.multiLineStrings;
    var isOperatorChar = /[+\-*&%=<>!?:\/|]/;
    function chain(stream, state, f) {
        state.tokenize = f;
        return f(stream, state);
    }

    function ret(tp, style) {
        type = tp;
        return style;
    }

    function tokenBase(stream, state) {
        var ch = stream.next();
        // start of string?
        if (ch == '"' || ch == "'")
            return chain(stream, state, tokenString(ch));
        // is it one of the special signs {}().,;? Seperator?
        else if (/[{}\(\),;\.]/.test(ch))
            return ret("bracket", "bracket");
        // start of a number value?
        else if (/\d/.test(ch)) {
            stream.eatWhile(/[\w\.]/);
            return ret("number", "number");
        }
        // multi line comment or simple operator?
        else if (ch == "/") {
            if (stream.eat("*")) {
                return chain(stream, state, tokenComment);
            } else {
                stream.eatWhile(isOperatorChar);
                return ret("operator", "operator");
            }
        }
        // single line comment or simple operator?
        else if (ch == "-") {
            if (stream.eat("-")) {
                stream.skipToEnd();
                return ret("comment", "comment");
            } else {
                stream.eatWhile(isOperatorChar);
                return ret("operator", "operator");
            }
        }
        // is it an identifier?
        else if (ch == "[") {
            return chain(stream, state, tokenString("]"));
        }
        // is it a operator?
        else if (isOperatorChar.test(ch)) {
            stream.eatWhile(isOperatorChar);
            return ret("operator", "operator");
        } else {
            // get the whole word
            stream.eatWhile(/[\w\$_]/);
            // is it one of the listed keywords?
            if (keywords
                && keywords.propertyIsEnumerable(stream
                                                 .current().toLowerCase()))
                return ret("keyword", "keyword");
            // is it one of the listed functions?
            if (functions
                && functions.propertyIsEnumerable(stream
                                                  .current().toLowerCase()))
                return ret("keyword", "builtin");
            // is it one of the listed types?
            if (properties
                && properties.propertyIsEnumerable(stream
                                                   .current().toLowerCase()))
                return ret("keyword", "variable-2");
            // default: just a "variable"
            return ret("word", "variable");
        }
    }

    function tokenString(quote) {
        return function(stream, state) {
            var escaped = false, next, end = false;
            while ((next = stream.next()) != null) {
                if (next == quote && !escaped) {
                    end = true;
                    break;
                }
                escaped = !escaped && next == "\\";
            }
            if (end || !(escaped || multiLineStrings))
                state.tokenize = tokenBase;
            return ret("string", "qualifier");
        };
    }

    function tokenComment(stream, state) {
        var maybeEnd = false, ch;
        while (ch = stream.next()) {
            if (ch == "/" && maybeEnd) {
                state.tokenize = tokenBase;
                break;
            }
            maybeEnd = (ch == "*");
        }
        return ret("comment", "comment");
    }

    // Interface
    return {
        startState : function(basecolumn) {
            return {
                tokenize : tokenBase,
                startOfLine : true
            };
        },

        token : function(stream, state) {
            if (stream.eatSpace())
                return null;
            var style = state.tokenize(stream, state);
            return style;
        }
    };
};

function keywords(str) {
    var obj = {}, words = str.split(" ");
    for ( var i = 0; i < words.length; ++i)
        obj[words[i]] = true;
    return obj;
}

var mdxKeywords = "select from on columns rows where with not in properties";

var mdxFunctions = "hierarchize crossjoin union filter iif format exists except " +
        "dateDiff dateAdd bottomCount bottomSum";

var mdxProperties = "null children descendants members firstChild firstSibling lastChild " +
        "lastSibling parent name uniqueName nextMember hierarchy dimension currentMember " +
        "defaultMember allMembers";

var mdxMime = {
    name : "mdx",
    keywords : keywords(mdxKeywords),
    functions : keywords(mdxFunctions),
    properties : keywords(mdxProperties)
};


module.exports = { mdxType: mdxMode, mdxMime: mdxMime };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant