To implement a runmode-like functionality with CM6, use the @codemirror/highlight
package like so
import {highlightTree, defaultHighlightStyle} from "@codemirror/highlight"
export function runmode(textContent: string, language: Language, callback: (text: string, style: string, from: number, to: number) => void, options?: Record<string, any>) {
const tree = language.parseString(textContent);
let pos = 0;
highlightTree(tree, defaultHighlightStyle.match, (from, to, classes) => {
from > pos && callback(textContent.slice(pos, from), null, pos, from);
callback(textContent.slice(from, to), classes, from, to);
pos = to;
});
pos != tree.length && callback(textContent.slice(pos, tree.length), null, pos, tree.length);
}
The reason why we need to keep a position state is because unstyled tokens are not emitted.
Note that in my experience, although dynamically loading languages is easier in CM6 because its given as es modules, I’ve found the overall bundle size required to replicate the runmode functionality larger because @codemirror/highlight
depends on @codemirror/view
and @codemirror/state
but 1. that may be tree-shaking misconfiguration 2. if you’re highlighting in server, bundle size might not be a problem.