Elegant way to support a ton of languages

I am working on a pastebin-like website, and trying to switch to using CodeMirror v6, the issue is supporting all of the languages that the old CodeMirror supported.

The website is paste.myst.rs, and there you can see the dropdown with all of the supported languages, and the way I did that was download all the languages, and dynamically import the proper language.

import(`../libs/codemirror/${mode}/${mode}.js`).then(() =>
    {
        editor.setOption("mode", mime);
    });

In v6, the languages are npm packages, and because I’m using rollup I can’t dynamically import npm modules. So for now I have this:

import { javascript } from "@codemirror/lang-javascript";
import { html } from "@codemirror/lang-html";
import { css } from "@codemirror/lang-css";
import { markdown } from "@codemirror/lang-markdown";
import { json } from "@codemirror/lang-json";
import { python } from "@codemirror/lang-python";
import { xml } from "@codemirror/lang-xml";
import { java } from "@codemirror/lang-java";
import { rust } from "@codemirror/lang-rust";
import { cpp } from "@codemirror/lang-cpp";
import { sql } from "@codemirror/lang-sql";
import { php } from "@codemirror/lang-php";

const onLangSelected = async () => {
    let ls: LanguageSupport = undefined;

    switch (selectedLanguage[0]) {
        case "JavaScript": ls = javascript(); break;
        case "HTML": ls = html(); break;
        case "CSS": ls = css(); break;
        case "Markdown": ls = markdown(); break;
        case "JSON": ls = json(); break;
        case "Python": ls = python(); break;
        case "XML": ls = xml(); break;
        case "Java": ls = java(); break;
        case "Rust": ls = rust(); break;
        case "C++": ls = cpp(); break;
        case "SQL": ls = sql(); break;
        case "PHP": ls = php(); break;
    }

    editorView.dispatch({
        effects: language.reconfigure(ls)
    });
};

This looks pretty ugly, and this doesn’t even include the “legacy” languages. So I wonder if there’s some solution to handling literally every language CM can support.

Have you seen the @codemirror/language-data package?

2 Likes

Oh… looks like that’s exactly what I would need, probably should be added to examples or something, pretty hard to find.

But just importing the package gives me an error:

[!] Error: UMD and IIFE output formats are not supported for code-splitting builds.
Error: UMD and IIFE output formats are not supported for code-splitting builds.
    at error (/home/codemyst/work/pastemyst/frontend/node_modules/rollup/dist/shared/rollup.js:5305:30)
    at validateOptionsForMultiChunkOutput (/home/codemyst/work/pastemyst/frontend/node_modules/rollup/dist/shared/rollup.js:12597:16)
    at Bundle.generate (/home/codemyst/work/pastemyst/frontend/node_modules/rollup/dist/shared/rollup.js:12436:17)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at handleGenerateWrite (/home/codemyst/work/pastemyst/frontend/node_modules/rollup/dist/shared/rollup.js:20306:23)
    at async Promise.all (index 0)
    at Task.run (/home/codemyst/work/pastemyst/frontend/node_modules/rollup/dist/shared/watch.js:756:32)
    at Watcher.run (/home/codemyst/work/pastemyst/frontend/node_modules/rollup/dist/shared/watch.js:683:13)

I set inlineDynamicImports to true in the rollup config and it seems to work now.

Thank you for the fast response, this is now working pretty great.