prosemirror-codemirror-block: CodeMirror 6 code block for ProseMirror
By Viktor on Wednesday, February 2, 2022

What's this about?

Release ProseMirror codeblock plugin that uses the brand-new CodeMirror 6, a major improvement over CodeMirror 5.

With:

  • Customizable language selector
  • lazy-loaded language support
  • works with YJS history

The code for this post is here

How to use?

  1. Install the plugin: npm i -S prosemirror-codemirror-block
  2. Import defaultSettings from the plugin ( and modify it if you want )
  3. Update the code_block node in the ProseMirror schema to have a lang attribute
  4. Initialize the editor with the plugin & insert keymaps for correct cursor handling around code_block

In codespeak:

1import { schema } from "prosemirror-schema-basic";
2import { EditorState } from "prosemirror-state";
3import { EditorView } from "prosemirror-view";
4import { exampleSetup } from "prosemirror-example-setup";
5import {
6    codeMirrorBlockPlugin,
7    defaultSettings,
8    languageLoaders,
9    codeBlockArrowHandlers,
10    legacyLanguageLoaders,
11} from "prosemirror-codemirror-block";
12import { undo, redo } from "prosemirror-history";
13
14
15const codeBlockSpec = schema.spec.nodes.get("code_block");
16
17export default new Schema({
18    nodes: schema.spec.nodes.update("code_block", {
19        ...(codeBlockSpec || {}),
20        attrs: { ...codeBlockSpec?.attrs, lang: { default: null } },
21    }),
22    marks: schema.spec.marks,
23});
24
25
26const codeBlockDoc = {
27    content: [
28        {
29            content: [
30                {
31                    text: "prosemirror-codemirror-block",
32                    type: "text",
33                },
34            ],
35            type: "paragraph",
36        },
37        {
38            content: [
39                {
40                    text: "const jsFun = (arg) => {\n  console.log(arg); \n}",
41                    type: "text",
42                },
43            ],
44            attrs: {
45                lang: "javascript",
46            },
47            type: "code_block",
48        },
49    ],
50    type: "doc",
51};
52
53
54const state = EditorState.create<typeof schema>({
55    doc: schema.nodeFromJSON(codeBlockDoc),
56    plugins: [
57        ...exampleSetup({
58            schema,
59        }),
60        codeMirrorBlockPlugin({
61            ...defaultSettings,
62            languageLoaders: { ...languageLoaders, ...legacyLanguageLoaders },
63            undo,
64            redo,
65        }),
66        keymap(codeBlockArrowHandlers),
67    ],
68});
69
70const view: EditorView = new EditorView(document.getElementById("editor"), {
71  state,
72});

You might also want to add

1.codeblock-select {
2    position: absolute;
3    right: 0;
4    z-index: 100;
5    opacity: 0;
6    transition: all 0.3s ease;
7    margin: 6px 14px;
8}
9.codeblock-root {
10    position: relative;
11}
12
13.codeblock-root:hover .codeblock-select {
14    opacity: 1;
15}

to the editor style in order to have a nicely positioned language selector.

Now....You have a better code_block, and the world just got a bit better.

You can check out the docs at https://gitlab.com/emergence-engineering/prosemirror-codemirror-block

Did you like this article? Would you like to learn more?
Write to us at contact@emergence-engineering.com