CodeMirror Modes: match subset of line with regex

538 Views Asked by At

I'm trying to create a mode overlay for CodeMirror.

I have a bunch of tested regular expressions that match sections of the line (from the stream), and I'd like if I could use these to match and tokenize part of the line.

For example:

# h1

Becomes:

<span class="..."><span class="cm-overlay cm-markup">#</span> h1</span>

Besides the simplemode addon, I'm not able to find any examples of using regular expressions in modes. This question is very similar to what I'm doing, but there are no answers about how to return the token for only a subset of the stream line: CodeMirror - Using RegEx with overlay

I managed to create the following mode which works, but matches the entire line, so produces html like: <span class="cm-overlay cm-markup"># h1</span>

CodeMirror.defineMode("markdown-extra", function() {
    return {
        token: function(stream, state) {
            markup = stream.match(/^([#]{1,6})[^#]/g); // matches markdown header syntax
            stream.skipToEnd();

            if (markup){
                console.log(markup, stream)
                return "markup"
            }

            return null
        }
    };
});

The documentation wants me to use stream.match to "eat" the matching characters, but doesn't mention how to only token a subsection while still using regular expressions.

I really have no idea how to continue.

1

There are 1 best solutions below

0
On

I figured it out somewhat.

I still don't fully understand why it works, but the following code matches the regex, but doesn't for some reason limit itself to the capture groups (the array is only 1 in size).

CodeMirror.defineMode("markdown-extra", function() {
        return {
            token: function(stream, state) {

                // ## header matching
                matchArray = stream.match(/^([#]{1,6}) /g);
                if (matchArray != null) {
                        var match = matchArray[0];
                        console.log(matchArray);
                        stream.match(match);
                        return "markup"
       }
                while (stream.next() != null && !stream.match(/^([#]{1,6})[^#]/g, false)) {}
      return null;

            }
        };
    });