ESM-compatible CodeMirror build (directly importable in browser)

The issue is that @codemirror/view and @codemirror/lang-javascript depend on different versions of @codemirror/state.

This is not a problem when using a bundler, but using esm.sh will cause both versions to be loaded which leads to a conflict. The codemirror package is especially problematic because it has three dependencies which all depend on different versions of @codemirror/state.

You can now specify dependencies with esm.sh:

import { basicSetup, EditorView } from "https://esm.sh/codemirror@6.0.1?deps=@codemirror/state@6.4.1";
import {javascript} from "https://esm.sh/@codemirror/lang-javascript?deps=@codemirror/state@6.4.1"

But this doesn’t work for transitive dependencies.

HOWEVER, you can also specify dependencies as external:

import { basicSetup, EditorView } from "https://esm.sh/codemirror@6.0.1?external=@codemirror/state";
import {javascript} from "https://esm.sh/@codemirror/lang-javascript?external=@codemirror/state"

Do that, and pin @codemirror/state to an exact version.

    <script type="importmap">
      {
        "imports": {
          "@codemirror/state": "https://esm.sh/@codemirror/state@6.5.0"
        }
      }
    </script>

That works great.

Edit: still works not so great.

Automatic indentation fails. When I add the no-bundle parameter, that works, but syntax highlighting is still broken.


Edit2: Finally got it to work.

<script type="importmap">
  {
    "imports": {
      "style-mod": "https://esm.sh/style-mod",
      "w3c-keyname": "https://esm.sh/w3c-keyname",
      "crelt": "https://esm.sh/crelt",
      "@marijn/find-cluster-break": "https://esm.sh/@marijn/find-cluster-break",
      "@lezer/": "https://esm.sh/*@lezer/",
      "@codemirror/": "https://esm.sh/*@codemirror/",
      "codemirror": "https://esm.sh/*codemirror"
    }
  }
</script>

Then simply import as:

import { basicSetup, EditorView } from "codemirror";
import { javascript } from "@codemirror/lang-javascript"

This will ensure that everything uses the same versions. Of course, you’ll probably want to pin top-level dependencies to a specific version.