Ionaru / easy-markdown-editor

EasyMDE: A simple, beautiful, and embeddable JavaScript Markdown editor. Delightful editing for beginners and experts alike. Features built-in autosaving and spell checking.
https://stackblitz.com/edit/easymde
MIT License
2.32k stars 308 forks source link

How to make the overlayMode working? #495

Open naitsok opened 1 year ago

naitsok commented 1 year ago

Hello to all the developers of EasyMDE. Thanks for such a great editor!

I would like add additional highlighting during editing. In particular, I want to highlight TeX/LaTeX equations. I've found the CodeMirrors's "stex" mode, but I'm struggling to make it load using the overlayMode option.

What I've done: I followed this guide on Hinty to add "stex" mode to the easymde.min.js. Everything should be correct as the size of easymde.min.js increased after adding "stex" mode.

Next, I tried different options to add the "stex" mode to overlayMode:

overlayMode: {
            mode: { name: "stex", inMathMode: false },
            combine: true,
        },

Then I've tried to create the mode object using CodeMirror.defineMode(...), and CodeMirror.getMode(...).

However, with no success in parsing and highlighting LaTeX equations during the editing. I'm sure that the solution is simple, but I couldn't get it working after searching and reading CodeMirror's docs. What am I doing wrong? Thanks a lot!

Ionaru commented 1 year ago

Highlighting LaTeX inside code blocks is pretty simple, all it takes is adding require('codemirror/mode/stex/stex.js'); to easymde.js and building a new dist. (hljs for highlighting in the preview).

image

Highlighting outside a code block is slightly trickier, but the overlayMode option is able to do what you need, given the right parameters, without having to edit the source.

const easyMDE = new EasyMDE({
    overlayMode: {
        mode: CodeMirror.getMode({}, 'stex'),
        combine: true,
    },
    spellChecker: false, // Does not work with the spell checker enabled.
});

Unfortunately the CodeMirror object from EasyMDE is not available at that moment, although exposing it on the EasyMDE object should not be difficult (EasyMDE.CodeMirror = CodeMirror; in easymde.js, PR anyone? šŸ˜‰).

Alternatively you can use https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.8/codemirror.min.js or any cdn of your choice to load in a copy of CodeMirror, yes it's a bit wasteful to load CodeMirror twice, but it's only 51 kb so šŸ¤·ā€ā™‚ļø.

After setting CodeMirror on the window you can load in https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.8/mode/stex/stex.min.js or any source for that module of your choice.

In the end my working editor looked like this:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>LaTeX</title>

    <link rel="stylesheet" href="https://unpkg.com/easymde/dist/easymde.min.css">
    <script src="https://unpkg.com/easymde/dist/easymde.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.8/codemirror.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.8/mode/stex/stex.min.js"></script>
</head>

<body>
    <textarea></textarea>
    <script>
        const easyMDE = new EasyMDE({
            overlayMode: {
                mode: CodeMirror.getMode({}, 'stex'),
                combine: true,
            },
            spellChecker: false,
        });
    </script>
</body>
</html>

image

I hope this helps you!

naitsok commented 1 year ago

Dear Jeroen, Thanks a lot for such a detailed and clear answer! Now surely I will be able to make it working. With best regards, Konstantin

sn3p commented 1 year ago

Since exposing CodeMirror isn't an options anymore, I've came up with a workaround that might work for other as well. It basically comes down to applying the mode after initialization:

const easyMDE = new EasyMDE({
  spellChecker: false
});

const stexMode = easyMDE.codemirror.constructor.getMode({}, "stex");

easyMDE.codemirror.setOption("mode", stexMode);

You might need to combine/multiplex the desired mode with the "gfm" mode, for example see: https://discuss.codemirror.net/t/combine-multiple-modes-htmlmixed-and-stex/3299

@Ionaru a possible bug I encountered is when using overlayMode, options in parsingConfig are ignored. See https://codepen.io/snap/pen/xxJrdaq. Thoughts? I can create a separate issue if you like.