==== Background
With CodeMirror 5, the `CodeMirror` object is in the global scope, making it simple for extensions to integrate with it. The 2017 wikitext editor (part of VisualEditor) does this with [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/CodeMirror/+/1651e7e3e2b9c9890573b1bbabdea07ca939ba9a/resources/modules/ve-cm/ve.ui.CodeMirrorAction.js | ve.ui.CodeMirrorAction.js ]] and [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/CodeMirror/+/1651e7e3e2b9c9890573b1bbabdea07ca939ba9a/resources/modules/ve-cm/ve.ui.CodeMirrorTool.js | ve.ui.CodeMirrorTool.js ]], which live in #mediawiki-extensions-codemirror and registered as a PluginModule for VisualEditor. My naive interpretation is that the module binds listeners to the core CodeMirror library, and adds a mirrored `ve.ui.Surface` on top of the original Surface.
This strategy won't work in CodeMirror 6, as CodeMirror is no longer in the global scope. Additionally, CM6 requires the use of ECMAScript modules, which are currently not supported by ResourceLoader (T281781).
This task is to explore options on how to address the VE integration.
==== Possible solutions
**Rewrite to use ECMAScript modules**
The `ext.CodeMirror.visualEditor` module could be rewritten as a ES6 class, extending the [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/CodeMirror/+/1651e7e3e2b9c9890573b1bbabdea07ca939ba9a/src/codemirror.js?autodive=0%2F | CodeMirror ]] class to get the essential logic, and making whatever additional changes and overrides as necessary.
This could work similar to the following:
```lang=javascript
// src/codeMirror.visualEditor.js
import CodeMirror from './codemirror';
import { mediaWikiLang } from './codemirror.mode.mediawiki';
class CodeMirrorVisualEditor extends CodeMirror {
// override methods as necessary, such as initialize()
}
const cm = new CodeMirror( veSurface );
cm.initialize( [ ...cm.defaultExtensions, mediaWikiLang() ] );
```
We then bundle the compiled JS as a separate file in the dist/ directory, making it accessible to ResourceLoader, and thus can be passed as a PluginModule to VisualEditor.
This to me seems like the most sensible approach, but will require considerable work.
**Use JS hooks**
A hook could be added to CM6, such that when there's any change to the [[ https://codemirror.net/docs/ref/#state.EditorState | EditorState ]], we fire off a hook with the [[ https://codemirror.net/docs/ref/#state.Transaction | Transaction ]]. We can give a more consumable data format if needed, as otherwise you may need to `import` CodeMirror classes in order to make use of the transaction data. The VE plugin then just listens to that hook and does it's thing, hopefully with minimal changes to existing code (?).
**Status-quo**
We also can simply let the old CM5 library remain for the time being. This isWe've decided to give it the easiest route,deprecation treatment, so it will likely be a while before the CM5 modules are removed. but means the 2017 editor won't get any of the new features and updates that come with CM6.This is the easiest route, #community-tech also likelybut means the 2017 editor won't be able to provide maintenance support for CM5 for very longget any of the new features and updates that come with CM6.