Giving Tags multiple styles/classes

I’m with the Wikimedia Foundation, one of the sponsors of CodeMirror 6. I’m currently trying to port our legacy stream parser for the mediawiki language to CodeMirror 6 and running into some trouble.

In CodeMirror 5, “multiple styles can be returned (separated by spaces)” when you have a mode object implementing token(), for example:

…
token: ( stream, state ) => {
	…
	return "strong error";
}

In CodeMirror 6 however, attempting this will throw a warning: Unknown highlighting tag strong error. It seems it only likes single styles/classes to be returned, I guess unless you define another tag called strong error.

Consider our admittedly ugly language, where you can have nested templates (for our purposes, let’s just think of these as function calls):

'''{{foo|{{bar}}}}'''

In our case, we want each nesting of {{ to be a tiny bit darker, to distinguish between the two levels of template calls. Finally, the outer ''' means all the content should be in bold. Our stream parser does this by keeping track of the nesting, and emitting a sequential number, so the first {{ might have .cm-bracket1 and the second {{ and first closing }} would have .cm-bracket2. However we again also want all of it bold, so ideally we’d return both strong and the custom classes for each token.

I can get around this by using a unique tag for bold + nesting of templates, but it gets a bit messy (imagine how many other combinations there are):

… = {
	tokenTable: {
		'bracket1': Tag.define(),
		'bracket2': Tag.define(),
		'bold-bracket1': Tag.define(),
		'bold-bracket2': Tag.define(),
	}
};

…

HighlightStyle.define( [
	{
		tag: myConfig.tokenTable[ 'bracket1' ],
		class: 'cm-bracket1'
	},
	{
		tag: myConfig.tokenTable[ 'bracket2' ],
		class: 'cm-bracket2'
	},
	{
		tag: myConfig.tokenTable[ 'bold-bracket1' ],
		class: 'strong cm-bracket1'
	},
	{
		tag: myConfig.tokenTable[ 'bold-bracket2' ],
		class: 'strong cm-bracket2'
	}
] );

How can I programmatically give a tag multiple styles (i.e. CSS class names)?

In simplest words, what is the CodeMirror 6 equivalent for this excerpt from the docs?

A typical token string would be "variable" or "comment". Multiple styles can be returned (separated by spaces), for example "string error" for a thing that looks like a string but is invalid somehow (say, missing its closing quote).

Thanks in advance!

That wasn’t possible, but there was no real reason for that. This patch adds support for it.

2 Likes

Amazing! I checked out the main branch of @codemirror/language, and now everything seems to work perfectly. Thank you for acting on this so quickly! :slight_smile: