Search code examples
codemirror

CodeMirror JSX highlighting broken


I'm trying to set up CodeMirror v6, but it seems the syntax highlighting is completely broken for JSX. End tags are given different classes from start tags, text content isn't differentiated from tags, and there's no way to easily extend the base theme to correct this -- I'm not going to re-implement an entire theme myself.

Here's the code I'm working with, and I'm using the latest versions of all packages:

import { EditorView } from 'codemirror';
import { EditorState } from '@codemirror/state';
import { javascript } from '@codemirror/lang-javascript';
import {
  syntaxHighlighting,
  defaultHighlightStyle,
} from '@codemirror/language';
import { oneDark } from '@codemirror/theme-one-dark';

const jsxString = `import { useState } from 'react';
import { render } from 'react-dom'

function Counter() {
    const [value, setValue] = useState(0);

    return (
        <>
            <div>Counter: {value}</div>
            <button onClick={() => setValue(value + 1)}>Increment</button>
            <button onClick={() => setValue(value - 1)}>Decrement</button>
        </>
    );
}

render(<Counter />, document.getElementById('app'));
`;

const state = EditorState.create({
  doc: jsxString,
  extensions: [
    javascript(),
    syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
    oneDark,
  ],
});

const view = new EditorView({
  state,
  parent: document.getElementById('root'),
});

Here's a picture of the rendered output

This seems fundamentally broken at the moment, and I'm not sure what's going wrong. Is there some lang-jsx package under another namespace? I already checked there wasn't one under @codemirror.

codemirror v5 comparatively works so much better that I have to imagine I'm doing something wrong.


Solution

  • Well, I feel silly. There's a (seemingly entirely undocumented) jsx option in the JavaScript extension:

    -    javascript(),
    +    javascript({ jsx: true }),
    

    Weird that syntax highlighting somewhat works without it (as < and > are totally invalid syntax)