Isolate build step to CM6 library and restructure files to work with RL
CodeMirror 6 requires the use of NPM, but we can still bundle all CM
packages into one file, and then everything else (i.e. our code) is
managed by ResourceLoader as per usual. This makes contribution
considerably easier as we no longer need a build step for each change.
CM5 files are now under resources/legacy, and the CM6 files are moved to
the root of the resources/ directory. Only one file,
codemirror.bundle.js, is managed by Rollup, while everything else is RL.
The Rollup output for now is put under resources/lib/ alongside the CM5
upstream files.
This patch is *mostly* renames of files, along with changing ECMAScript
Module (ESM) syntax into the CommonJS style that ResourceLoader prefers.
We also remove more modern JS syntax (i.e. private class methods) that
we were able to use before because we had a build step with Babel.
This patch should effectively make no user-facing changes, or to the
ResourceLoader modules we offer in Extension:CodeMirror.
Finally, bump version in extension.json to 6, to match the upstream lib,
and add Bhsd as an author :-)
Bug: T368053
Change-Id: Ie258e49f5df8db23a7344ac3c4c9300aaa991042
2024-06-21 03:21:09 +00:00
|
|
|
const {
|
CodeMirrorPreferences: add panel to tweak prefs with the editor open
This is toggled by pressing Mod-Shift-, (or Command-Shift-, on MacOS),
which then puts focus on the preferences panel. It can be closed with
the Escape key, just like other CM panels.
The CodeMirror class comes with these extension which can be toggled in
preferences:
* Bracket matching
* Line numbering
* Line wrapping
* Highlight the active line
* Show special characters
Only bracket matching, line numbering, and line wrapping are available
in the 2017 editor.
The bidi isolation and template folding extensions are registered in
CodeMirrorModeMediaWiki as they are MW-specific. CodeMirrorPreferences'
new registerExtension() method allows any consumer of CodeMirror to add
any arbitrary extensions to the preferences panel. This is expected to
be called *after* CodeMirror has finished initializing. The
'ext.CodeMirror.ready' hook now passes the CodeMirror instance to
accommodate this.
The preferences are stored as a single user option in the database,
called 'codemirror-preferences'. The defaults can be configured with the
$wgCodeMirrorDefaultPreferences configuration setting. The
sysadmin-facing values are the familiar boolean, but since CodeMirror is
widely used, we make extra efforts to reduce the storage footprint (see
T54777). This includes only storing preferences that differ from the
defaults, and using binary representation instead of boolean values,
since the user option is stored as a string.
For now, all preferences are ignored in the 2017 editor. In a future
patch, we may add some as toggleable Tools in the VE toolbar.
Other changes:
* Refactor CSS to use a .darkmode() mixin
* Add a method to create a CSS-only fieldset in CodeMirrorPanel
* Fix Jest tests now that there are more calls to mw.user.options.get()
* Adjust Selenium tests to always use CM6
* Adjust Selenium tests to delete test pages (useful for local dev)
* Remove unused code
Bug: T359498
Change-Id: I70dcf2f49418cea632c452c1266440effad634f3
2024-08-16 01:52:13 +00:00
|
|
|
Compartment,
|
Isolate build step to CM6 library and restructure files to work with RL
CodeMirror 6 requires the use of NPM, but we can still bundle all CM
packages into one file, and then everything else (i.e. our code) is
managed by ResourceLoader as per usual. This makes contribution
considerably easier as we no longer need a build step for each change.
CM5 files are now under resources/legacy, and the CM6 files are moved to
the root of the resources/ directory. Only one file,
codemirror.bundle.js, is managed by Rollup, while everything else is RL.
The Rollup output for now is put under resources/lib/ alongside the CM5
upstream files.
This patch is *mostly* renames of files, along with changing ECMAScript
Module (ESM) syntax into the CommonJS style that ResourceLoader prefers.
We also remove more modern JS syntax (i.e. private class methods) that
we were able to use before because we had a build step with Babel.
This patch should effectively make no user-facing changes, or to the
ResourceLoader modules we offer in Extension:CodeMirror.
Finally, bump version in extension.json to 6, to match the upstream lib,
and add Bhsd as an author :-)
Bug: T368053
Change-Id: Ie258e49f5df8db23a7344ac3c4c9300aaa991042
2024-06-21 03:21:09 +00:00
|
|
|
EditorState,
|
2024-05-03 08:34:50 +00:00
|
|
|
EditorView,
|
Isolate build step to CM6 library and restructure files to work with RL
CodeMirror 6 requires the use of NPM, but we can still bundle all CM
packages into one file, and then everything else (i.e. our code) is
managed by ResourceLoader as per usual. This makes contribution
considerably easier as we no longer need a build step for each change.
CM5 files are now under resources/legacy, and the CM6 files are moved to
the root of the resources/ directory. Only one file,
codemirror.bundle.js, is managed by Rollup, while everything else is RL.
The Rollup output for now is put under resources/lib/ alongside the CM5
upstream files.
This patch is *mostly* renames of files, along with changing ECMAScript
Module (ESM) syntax into the CommonJS style that ResourceLoader prefers.
We also remove more modern JS syntax (i.e. private class methods) that
we were able to use before because we had a build step with Babel.
This patch should effectively make no user-facing changes, or to the
ResourceLoader modules we offer in Extension:CodeMirror.
Finally, bump version in extension.json to 6, to match the upstream lib,
and add Bhsd as an author :-)
Bug: T368053
Change-Id: Ie258e49f5df8db23a7344ac3c4c9300aaa991042
2024-06-21 03:21:09 +00:00
|
|
|
Extension,
|
2024-05-24 21:20:04 +00:00
|
|
|
KeyBinding,
|
Isolate build step to CM6 library and restructure files to work with RL
CodeMirror 6 requires the use of NPM, but we can still bundle all CM
packages into one file, and then everything else (i.e. our code) is
managed by ResourceLoader as per usual. This makes contribution
considerably easier as we no longer need a build step for each change.
CM5 files are now under resources/legacy, and the CM6 files are moved to
the root of the resources/ directory. Only one file,
codemirror.bundle.js, is managed by Rollup, while everything else is RL.
The Rollup output for now is put under resources/lib/ alongside the CM5
upstream files.
This patch is *mostly* renames of files, along with changing ECMAScript
Module (ESM) syntax into the CommonJS style that ResourceLoader prefers.
We also remove more modern JS syntax (i.e. private class methods) that
we were able to use before because we had a build step with Babel.
This patch should effectively make no user-facing changes, or to the
ResourceLoader modules we offer in Extension:CodeMirror.
Finally, bump version in extension.json to 6, to match the upstream lib,
and add Bhsd as an author :-)
Bug: T368053
Change-Id: Ie258e49f5df8db23a7344ac3c4c9300aaa991042
2024-06-21 03:21:09 +00:00
|
|
|
ViewUpdate,
|
|
|
|
bracketMatching,
|
|
|
|
crosshairCursor,
|
|
|
|
defaultKeymap,
|
2024-05-03 08:34:50 +00:00
|
|
|
drawSelection,
|
CodeMirrorPreferences: add panel to tweak prefs with the editor open
This is toggled by pressing Mod-Shift-, (or Command-Shift-, on MacOS),
which then puts focus on the preferences panel. It can be closed with
the Escape key, just like other CM panels.
The CodeMirror class comes with these extension which can be toggled in
preferences:
* Bracket matching
* Line numbering
* Line wrapping
* Highlight the active line
* Show special characters
Only bracket matching, line numbering, and line wrapping are available
in the 2017 editor.
The bidi isolation and template folding extensions are registered in
CodeMirrorModeMediaWiki as they are MW-specific. CodeMirrorPreferences'
new registerExtension() method allows any consumer of CodeMirror to add
any arbitrary extensions to the preferences panel. This is expected to
be called *after* CodeMirror has finished initializing. The
'ext.CodeMirror.ready' hook now passes the CodeMirror instance to
accommodate this.
The preferences are stored as a single user option in the database,
called 'codemirror-preferences'. The defaults can be configured with the
$wgCodeMirrorDefaultPreferences configuration setting. The
sysadmin-facing values are the familiar boolean, but since CodeMirror is
widely used, we make extra efforts to reduce the storage footprint (see
T54777). This includes only storing preferences that differ from the
defaults, and using binary representation instead of boolean values,
since the user option is stored as a string.
For now, all preferences are ignored in the 2017 editor. In a future
patch, we may add some as toggleable Tools in the VE toolbar.
Other changes:
* Refactor CSS to use a .darkmode() mixin
* Add a method to create a CSS-only fieldset in CodeMirrorPanel
* Fix Jest tests now that there are more calls to mw.user.options.get()
* Adjust Selenium tests to always use CM6
* Adjust Selenium tests to delete test pages (useful for local dev)
* Remove unused code
Bug: T359498
Change-Id: I70dcf2f49418cea632c452c1266440effad634f3
2024-08-16 01:52:13 +00:00
|
|
|
highlightActiveLine,
|
2024-05-03 08:34:50 +00:00
|
|
|
highlightSpecialChars,
|
Isolate build step to CM6 library and restructure files to work with RL
CodeMirror 6 requires the use of NPM, but we can still bundle all CM
packages into one file, and then everything else (i.e. our code) is
managed by ResourceLoader as per usual. This makes contribution
considerably easier as we no longer need a build step for each change.
CM5 files are now under resources/legacy, and the CM6 files are moved to
the root of the resources/ directory. Only one file,
codemirror.bundle.js, is managed by Rollup, while everything else is RL.
The Rollup output for now is put under resources/lib/ alongside the CM5
upstream files.
This patch is *mostly* renames of files, along with changing ECMAScript
Module (ESM) syntax into the CommonJS style that ResourceLoader prefers.
We also remove more modern JS syntax (i.e. private class methods) that
we were able to use before because we had a build step with Babel.
This patch should effectively make no user-facing changes, or to the
ResourceLoader modules we offer in Extension:CodeMirror.
Finally, bump version in extension.json to 6, to match the upstream lib,
and add Bhsd as an author :-)
Bug: T368053
Change-Id: Ie258e49f5df8db23a7344ac3c4c9300aaa991042
2024-06-21 03:21:09 +00:00
|
|
|
history,
|
|
|
|
historyKeymap,
|
2024-12-03 08:58:10 +00:00
|
|
|
indentUnit,
|
2024-05-03 08:34:50 +00:00
|
|
|
keymap,
|
Isolate build step to CM6 library and restructure files to work with RL
CodeMirror 6 requires the use of NPM, but we can still bundle all CM
packages into one file, and then everything else (i.e. our code) is
managed by ResourceLoader as per usual. This makes contribution
considerably easier as we no longer need a build step for each change.
CM5 files are now under resources/legacy, and the CM6 files are moved to
the root of the resources/ directory. Only one file,
codemirror.bundle.js, is managed by Rollup, while everything else is RL.
The Rollup output for now is put under resources/lib/ alongside the CM5
upstream files.
This patch is *mostly* renames of files, along with changing ECMAScript
Module (ESM) syntax into the CommonJS style that ResourceLoader prefers.
We also remove more modern JS syntax (i.e. private class methods) that
we were able to use before because we had a build step with Babel.
This patch should effectively make no user-facing changes, or to the
ResourceLoader modules we offer in Extension:CodeMirror.
Finally, bump version in extension.json to 6, to match the upstream lib,
and add Bhsd as an author :-)
Bug: T368053
Change-Id: Ie258e49f5df8db23a7344ac3c4c9300aaa991042
2024-06-21 03:21:09 +00:00
|
|
|
lineNumbers,
|
2024-05-03 08:34:50 +00:00
|
|
|
rectangularSelection,
|
2024-08-01 21:39:43 +00:00
|
|
|
redo
|
Isolate build step to CM6 library and restructure files to work with RL
CodeMirror 6 requires the use of NPM, but we can still bundle all CM
packages into one file, and then everything else (i.e. our code) is
managed by ResourceLoader as per usual. This makes contribution
considerably easier as we no longer need a build step for each change.
CM5 files are now under resources/legacy, and the CM6 files are moved to
the root of the resources/ directory. Only one file,
codemirror.bundle.js, is managed by Rollup, while everything else is RL.
The Rollup output for now is put under resources/lib/ alongside the CM5
upstream files.
This patch is *mostly* renames of files, along with changing ECMAScript
Module (ESM) syntax into the CommonJS style that ResourceLoader prefers.
We also remove more modern JS syntax (i.e. private class methods) that
we were able to use before because we had a build step with Babel.
This patch should effectively make no user-facing changes, or to the
ResourceLoader modules we offer in Extension:CodeMirror.
Finally, bump version in extension.json to 6, to match the upstream lib,
and add Bhsd as an author :-)
Bug: T368053
Change-Id: Ie258e49f5df8db23a7344ac3c4c9300aaa991042
2024-06-21 03:21:09 +00:00
|
|
|
} = require( 'ext.CodeMirror.v6.lib' );
|
|
|
|
const CodeMirrorTextSelection = require( './codemirror.textSelection.js' );
|
2024-08-01 21:39:43 +00:00
|
|
|
const CodeMirrorSearch = require( './codemirror.search.js' );
|
|
|
|
const CodeMirrorGotoLine = require( './codemirror.gotoLine.js' );
|
CodeMirrorPreferences: add panel to tweak prefs with the editor open
This is toggled by pressing Mod-Shift-, (or Command-Shift-, on MacOS),
which then puts focus on the preferences panel. It can be closed with
the Escape key, just like other CM panels.
The CodeMirror class comes with these extension which can be toggled in
preferences:
* Bracket matching
* Line numbering
* Line wrapping
* Highlight the active line
* Show special characters
Only bracket matching, line numbering, and line wrapping are available
in the 2017 editor.
The bidi isolation and template folding extensions are registered in
CodeMirrorModeMediaWiki as they are MW-specific. CodeMirrorPreferences'
new registerExtension() method allows any consumer of CodeMirror to add
any arbitrary extensions to the preferences panel. This is expected to
be called *after* CodeMirror has finished initializing. The
'ext.CodeMirror.ready' hook now passes the CodeMirror instance to
accommodate this.
The preferences are stored as a single user option in the database,
called 'codemirror-preferences'. The defaults can be configured with the
$wgCodeMirrorDefaultPreferences configuration setting. The
sysadmin-facing values are the familiar boolean, but since CodeMirror is
widely used, we make extra efforts to reduce the storage footprint (see
T54777). This includes only storing preferences that differ from the
defaults, and using binary representation instead of boolean values,
since the user option is stored as a string.
For now, all preferences are ignored in the 2017 editor. In a future
patch, we may add some as toggleable Tools in the VE toolbar.
Other changes:
* Refactor CSS to use a .darkmode() mixin
* Add a method to create a CSS-only fieldset in CodeMirrorPanel
* Fix Jest tests now that there are more calls to mw.user.options.get()
* Adjust Selenium tests to always use CM6
* Adjust Selenium tests to delete test pages (useful for local dev)
* Remove unused code
Bug: T359498
Change-Id: I70dcf2f49418cea632c452c1266440effad634f3
2024-08-16 01:52:13 +00:00
|
|
|
const CodeMirrorPreferences = require( './codemirror.preferences.js' );
|
Isolate build step to CM6 library and restructure files to work with RL
CodeMirror 6 requires the use of NPM, but we can still bundle all CM
packages into one file, and then everything else (i.e. our code) is
managed by ResourceLoader as per usual. This makes contribution
considerably easier as we no longer need a build step for each change.
CM5 files are now under resources/legacy, and the CM6 files are moved to
the root of the resources/ directory. Only one file,
codemirror.bundle.js, is managed by Rollup, while everything else is RL.
The Rollup output for now is put under resources/lib/ alongside the CM5
upstream files.
This patch is *mostly* renames of files, along with changing ECMAScript
Module (ESM) syntax into the CommonJS style that ResourceLoader prefers.
We also remove more modern JS syntax (i.e. private class methods) that
we were able to use before because we had a build step with Babel.
This patch should effectively make no user-facing changes, or to the
ResourceLoader modules we offer in Extension:CodeMirror.
Finally, bump version in extension.json to 6, to match the upstream lib,
and add Bhsd as an author :-)
Bug: T368053
Change-Id: Ie258e49f5df8db23a7344ac3c4c9300aaa991042
2024-06-21 03:21:09 +00:00
|
|
|
require( './ext.CodeMirror.data.js' );
|
2024-03-11 18:10:08 +00:00
|
|
|
|
2023-09-19 17:59:29 +00:00
|
|
|
/**
|
2024-03-19 03:10:11 +00:00
|
|
|
* Interface for the CodeMirror editor.
|
|
|
|
*
|
|
|
|
* @example
|
|
|
|
* mw.loader.using( [
|
|
|
|
* 'ext.CodeMirror.v6',
|
|
|
|
* 'ext.CodeMirror.v6.mode.mediawiki'
|
|
|
|
* ] ).then( ( require ) => {
|
|
|
|
* const CodeMirror = require( 'ext.CodeMirror.v6' );
|
|
|
|
* const mediawikiLang = require( 'ext.CodeMirror.v6.mode.mediawiki' );
|
|
|
|
* const cm = new CodeMirror( myTextarea );
|
|
|
|
* cm.initialize( [ cm.defaultExtensions, mediawikiLang() ] );
|
|
|
|
* } );
|
2023-09-19 17:59:29 +00:00
|
|
|
*/
|
2024-03-19 03:10:11 +00:00
|
|
|
class CodeMirror {
|
2023-09-19 17:59:29 +00:00
|
|
|
/**
|
2024-03-19 03:10:11 +00:00
|
|
|
* Instantiate a new CodeMirror instance.
|
|
|
|
*
|
2024-06-08 03:10:11 +00:00
|
|
|
* @param {HTMLTextAreaElement|jQuery|string|ve.ui.Surface} textarea Textarea to
|
|
|
|
* add syntax highlighting to.
|
2024-03-19 03:10:11 +00:00
|
|
|
* @constructor
|
2023-09-19 17:59:29 +00:00
|
|
|
*/
|
2023-12-06 18:46:59 +00:00
|
|
|
constructor( textarea ) {
|
2024-06-08 03:10:11 +00:00
|
|
|
if ( textarea.constructor.name === 'VeUiMWWikitextSurface' ) {
|
|
|
|
/**
|
|
|
|
* The VisualEditor surface CodeMirror is bound to.
|
|
|
|
*
|
|
|
|
* @type {ve.ui.Surface}
|
|
|
|
*/
|
|
|
|
this.surface = textarea;
|
|
|
|
|
|
|
|
// Let the content editable mimic the textarea.
|
|
|
|
// eslint-disable-next-line no-jquery/variable-pattern
|
|
|
|
textarea = this.surface.getView().$attachedRootNode;
|
|
|
|
}
|
2024-03-19 03:10:11 +00:00
|
|
|
/**
|
|
|
|
* The textarea that CodeMirror is bound to.
|
2024-04-23 19:13:38 +00:00
|
|
|
*
|
2024-03-19 03:10:11 +00:00
|
|
|
* @type {jQuery}
|
|
|
|
*/
|
2023-12-06 18:46:59 +00:00
|
|
|
this.$textarea = $( textarea );
|
2024-03-19 03:10:11 +00:00
|
|
|
/**
|
|
|
|
* The editor user interface.
|
2024-04-23 19:13:38 +00:00
|
|
|
*
|
2024-03-19 03:10:11 +00:00
|
|
|
* @type {EditorView}
|
|
|
|
*/
|
2023-09-19 17:59:29 +00:00
|
|
|
this.view = null;
|
2024-03-19 03:10:11 +00:00
|
|
|
/**
|
|
|
|
* The editor state.
|
2024-04-23 19:13:38 +00:00
|
|
|
*
|
2024-03-19 03:10:11 +00:00
|
|
|
* @type {EditorState}
|
|
|
|
*/
|
2023-09-19 17:59:29 +00:00
|
|
|
this.state = null;
|
2024-03-19 03:10:11 +00:00
|
|
|
/**
|
|
|
|
* Whether the textarea is read-only.
|
2024-04-23 19:13:38 +00:00
|
|
|
*
|
2024-03-19 03:10:11 +00:00
|
|
|
* @type {boolean}
|
|
|
|
*/
|
2024-06-08 03:10:11 +00:00
|
|
|
this.readOnly = this.surface ?
|
|
|
|
this.surface.getModel().isReadOnly() :
|
|
|
|
this.$textarea.prop( 'readonly' );
|
2024-03-19 03:10:11 +00:00
|
|
|
/**
|
|
|
|
* The [edit recovery]{@link https://www.mediawiki.org/wiki/Manual:Edit_Recovery} handler.
|
2024-04-23 19:13:38 +00:00
|
|
|
*
|
2024-03-19 03:10:11 +00:00
|
|
|
* @type {Function|null}
|
|
|
|
*/
|
2024-03-11 21:03:28 +00:00
|
|
|
this.editRecoveryHandler = null;
|
2024-12-04 05:03:39 +00:00
|
|
|
/**
|
|
|
|
* The form `submit` event handler.
|
|
|
|
*
|
|
|
|
* @type {Function|null}
|
|
|
|
*/
|
|
|
|
this.formSubmitEventHandler = null;
|
2024-03-19 03:10:11 +00:00
|
|
|
/**
|
|
|
|
* jQuery.textSelection overrides for CodeMirror.
|
2024-04-23 19:13:38 +00:00
|
|
|
*
|
2024-03-19 03:10:11 +00:00
|
|
|
* @type {CodeMirrorTextSelection}
|
|
|
|
*/
|
2024-03-09 05:36:43 +00:00
|
|
|
this.textSelection = null;
|
2024-06-08 03:10:11 +00:00
|
|
|
/**
|
CodeMirrorPreferences: add panel to tweak prefs with the editor open
This is toggled by pressing Mod-Shift-, (or Command-Shift-, on MacOS),
which then puts focus on the preferences panel. It can be closed with
the Escape key, just like other CM panels.
The CodeMirror class comes with these extension which can be toggled in
preferences:
* Bracket matching
* Line numbering
* Line wrapping
* Highlight the active line
* Show special characters
Only bracket matching, line numbering, and line wrapping are available
in the 2017 editor.
The bidi isolation and template folding extensions are registered in
CodeMirrorModeMediaWiki as they are MW-specific. CodeMirrorPreferences'
new registerExtension() method allows any consumer of CodeMirror to add
any arbitrary extensions to the preferences panel. This is expected to
be called *after* CodeMirror has finished initializing. The
'ext.CodeMirror.ready' hook now passes the CodeMirror instance to
accommodate this.
The preferences are stored as a single user option in the database,
called 'codemirror-preferences'. The defaults can be configured with the
$wgCodeMirrorDefaultPreferences configuration setting. The
sysadmin-facing values are the familiar boolean, but since CodeMirror is
widely used, we make extra efforts to reduce the storage footprint (see
T54777). This includes only storing preferences that differ from the
defaults, and using binary representation instead of boolean values,
since the user option is stored as a string.
For now, all preferences are ignored in the 2017 editor. In a future
patch, we may add some as toggleable Tools in the VE toolbar.
Other changes:
* Refactor CSS to use a .darkmode() mixin
* Add a method to create a CSS-only fieldset in CodeMirrorPanel
* Fix Jest tests now that there are more calls to mw.user.options.get()
* Adjust Selenium tests to always use CM6
* Adjust Selenium tests to delete test pages (useful for local dev)
* Remove unused code
Bug: T359498
Change-Id: I70dcf2f49418cea632c452c1266440effad634f3
2024-08-16 01:52:13 +00:00
|
|
|
* Compartment to control the direction of the editor.
|
2024-06-08 03:10:11 +00:00
|
|
|
*
|
|
|
|
* @type {Compartment}
|
|
|
|
*/
|
|
|
|
this.dirCompartment = new Compartment();
|
2024-06-08 03:10:11 +00:00
|
|
|
/**
|
CodeMirrorPreferences: add panel to tweak prefs with the editor open
This is toggled by pressing Mod-Shift-, (or Command-Shift-, on MacOS),
which then puts focus on the preferences panel. It can be closed with
the Escape key, just like other CM panels.
The CodeMirror class comes with these extension which can be toggled in
preferences:
* Bracket matching
* Line numbering
* Line wrapping
* Highlight the active line
* Show special characters
Only bracket matching, line numbering, and line wrapping are available
in the 2017 editor.
The bidi isolation and template folding extensions are registered in
CodeMirrorModeMediaWiki as they are MW-specific. CodeMirrorPreferences'
new registerExtension() method allows any consumer of CodeMirror to add
any arbitrary extensions to the preferences panel. This is expected to
be called *after* CodeMirror has finished initializing. The
'ext.CodeMirror.ready' hook now passes the CodeMirror instance to
accommodate this.
The preferences are stored as a single user option in the database,
called 'codemirror-preferences'. The defaults can be configured with the
$wgCodeMirrorDefaultPreferences configuration setting. The
sysadmin-facing values are the familiar boolean, but since CodeMirror is
widely used, we make extra efforts to reduce the storage footprint (see
T54777). This includes only storing preferences that differ from the
defaults, and using binary representation instead of boolean values,
since the user option is stored as a string.
For now, all preferences are ignored in the 2017 editor. In a future
patch, we may add some as toggleable Tools in the VE toolbar.
Other changes:
* Refactor CSS to use a .darkmode() mixin
* Add a method to create a CSS-only fieldset in CodeMirrorPanel
* Fix Jest tests now that there are more calls to mw.user.options.get()
* Adjust Selenium tests to always use CM6
* Adjust Selenium tests to delete test pages (useful for local dev)
* Remove unused code
Bug: T359498
Change-Id: I70dcf2f49418cea632c452c1266440effad634f3
2024-08-16 01:52:13 +00:00
|
|
|
* The CodeMirror preferences panel.
|
2024-06-08 03:10:11 +00:00
|
|
|
*
|
CodeMirrorPreferences: add panel to tweak prefs with the editor open
This is toggled by pressing Mod-Shift-, (or Command-Shift-, on MacOS),
which then puts focus on the preferences panel. It can be closed with
the Escape key, just like other CM panels.
The CodeMirror class comes with these extension which can be toggled in
preferences:
* Bracket matching
* Line numbering
* Line wrapping
* Highlight the active line
* Show special characters
Only bracket matching, line numbering, and line wrapping are available
in the 2017 editor.
The bidi isolation and template folding extensions are registered in
CodeMirrorModeMediaWiki as they are MW-specific. CodeMirrorPreferences'
new registerExtension() method allows any consumer of CodeMirror to add
any arbitrary extensions to the preferences panel. This is expected to
be called *after* CodeMirror has finished initializing. The
'ext.CodeMirror.ready' hook now passes the CodeMirror instance to
accommodate this.
The preferences are stored as a single user option in the database,
called 'codemirror-preferences'. The defaults can be configured with the
$wgCodeMirrorDefaultPreferences configuration setting. The
sysadmin-facing values are the familiar boolean, but since CodeMirror is
widely used, we make extra efforts to reduce the storage footprint (see
T54777). This includes only storing preferences that differ from the
defaults, and using binary representation instead of boolean values,
since the user option is stored as a string.
For now, all preferences are ignored in the 2017 editor. In a future
patch, we may add some as toggleable Tools in the VE toolbar.
Other changes:
* Refactor CSS to use a .darkmode() mixin
* Add a method to create a CSS-only fieldset in CodeMirrorPanel
* Fix Jest tests now that there are more calls to mw.user.options.get()
* Adjust Selenium tests to always use CM6
* Adjust Selenium tests to delete test pages (useful for local dev)
* Remove unused code
Bug: T359498
Change-Id: I70dcf2f49418cea632c452c1266440effad634f3
2024-08-16 01:52:13 +00:00
|
|
|
* @type {CodeMirrorPreferences}
|
2024-06-08 03:10:11 +00:00
|
|
|
*/
|
CodeMirrorPreferences: add panel to tweak prefs with the editor open
This is toggled by pressing Mod-Shift-, (or Command-Shift-, on MacOS),
which then puts focus on the preferences panel. It can be closed with
the Escape key, just like other CM panels.
The CodeMirror class comes with these extension which can be toggled in
preferences:
* Bracket matching
* Line numbering
* Line wrapping
* Highlight the active line
* Show special characters
Only bracket matching, line numbering, and line wrapping are available
in the 2017 editor.
The bidi isolation and template folding extensions are registered in
CodeMirrorModeMediaWiki as they are MW-specific. CodeMirrorPreferences'
new registerExtension() method allows any consumer of CodeMirror to add
any arbitrary extensions to the preferences panel. This is expected to
be called *after* CodeMirror has finished initializing. The
'ext.CodeMirror.ready' hook now passes the CodeMirror instance to
accommodate this.
The preferences are stored as a single user option in the database,
called 'codemirror-preferences'. The defaults can be configured with the
$wgCodeMirrorDefaultPreferences configuration setting. The
sysadmin-facing values are the familiar boolean, but since CodeMirror is
widely used, we make extra efforts to reduce the storage footprint (see
T54777). This includes only storing preferences that differ from the
defaults, and using binary representation instead of boolean values,
since the user option is stored as a string.
For now, all preferences are ignored in the 2017 editor. In a future
patch, we may add some as toggleable Tools in the VE toolbar.
Other changes:
* Refactor CSS to use a .darkmode() mixin
* Add a method to create a CSS-only fieldset in CodeMirrorPanel
* Fix Jest tests now that there are more calls to mw.user.options.get()
* Adjust Selenium tests to always use CM6
* Adjust Selenium tests to delete test pages (useful for local dev)
* Remove unused code
Bug: T359498
Change-Id: I70dcf2f49418cea632c452c1266440effad634f3
2024-08-16 01:52:13 +00:00
|
|
|
this.preferences = new CodeMirrorPreferences( {
|
|
|
|
bracketMatching: this.bracketMatchingExtension,
|
|
|
|
lineNumbering: this.lineNumberingExtension,
|
|
|
|
lineWrapping: this.lineWrappingExtension,
|
|
|
|
activeLine: this.activeLineExtension,
|
|
|
|
specialChars: this.specialCharsExtension
|
|
|
|
}, !!this.surface );
|
2023-09-19 17:59:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-03-19 03:10:11 +00:00
|
|
|
* Default extensions used by CodeMirror.
|
2023-09-19 17:59:29 +00:00
|
|
|
* Extensions here should be applicable to all theoretical uses of CodeMirror in MediaWiki.
|
|
|
|
*
|
2023-10-11 02:00:08 +00:00
|
|
|
* @see https://codemirror.net/docs/ref/#state.Extension
|
2024-03-19 03:10:11 +00:00
|
|
|
* @type {Extension|Extension[]}
|
|
|
|
* @stable to call
|
2023-09-19 17:59:29 +00:00
|
|
|
*/
|
|
|
|
get defaultExtensions() {
|
2023-10-11 02:00:08 +00:00
|
|
|
const extensions = [
|
2024-01-13 03:21:12 +00:00
|
|
|
this.contentAttributesExtension,
|
2024-01-19 00:33:58 +00:00
|
|
|
this.phrasesExtension,
|
2024-01-10 00:02:44 +00:00
|
|
|
this.heightExtension,
|
2024-04-15 17:30:49 +00:00
|
|
|
this.updateExtension,
|
2024-06-08 03:10:11 +00:00
|
|
|
this.dirExtension,
|
2024-08-01 21:39:43 +00:00
|
|
|
this.searchExtension,
|
CodeMirrorPreferences: add panel to tweak prefs with the editor open
This is toggled by pressing Mod-Shift-, (or Command-Shift-, on MacOS),
which then puts focus on the preferences panel. It can be closed with
the Escape key, just like other CM panels.
The CodeMirror class comes with these extension which can be toggled in
preferences:
* Bracket matching
* Line numbering
* Line wrapping
* Highlight the active line
* Show special characters
Only bracket matching, line numbering, and line wrapping are available
in the 2017 editor.
The bidi isolation and template folding extensions are registered in
CodeMirrorModeMediaWiki as they are MW-specific. CodeMirrorPreferences'
new registerExtension() method allows any consumer of CodeMirror to add
any arbitrary extensions to the preferences panel. This is expected to
be called *after* CodeMirror has finished initializing. The
'ext.CodeMirror.ready' hook now passes the CodeMirror instance to
accommodate this.
The preferences are stored as a single user option in the database,
called 'codemirror-preferences'. The defaults can be configured with the
$wgCodeMirrorDefaultPreferences configuration setting. The
sysadmin-facing values are the familiar boolean, but since CodeMirror is
widely used, we make extra efforts to reduce the storage footprint (see
T54777). This includes only storing preferences that differ from the
defaults, and using binary representation instead of boolean values,
since the user option is stored as a string.
For now, all preferences are ignored in the 2017 editor. In a future
patch, we may add some as toggleable Tools in the VE toolbar.
Other changes:
* Refactor CSS to use a .darkmode() mixin
* Add a method to create a CSS-only fieldset in CodeMirrorPanel
* Fix Jest tests now that there are more calls to mw.user.options.get()
* Adjust Selenium tests to always use CM6
* Adjust Selenium tests to delete test pages (useful for local dev)
* Remove unused code
Bug: T359498
Change-Id: I70dcf2f49418cea632c452c1266440effad634f3
2024-08-16 01:52:13 +00:00
|
|
|
this.preferences.extension,
|
2024-12-03 08:58:10 +00:00
|
|
|
indentUnit.of( '\t' ),
|
2024-03-11 21:03:28 +00:00
|
|
|
EditorState.readOnly.of( this.readOnly ),
|
CM6: Add syntax highlighting preference for users without WikiEditor
This adds the `ext.CodeMirror.v6.init` ResourceLoader module which
allows use of CodeMirror on `#wpTextbox1` without the use of WikiEditor
(the 'usebetatoolbar' preference). In order for users to opt-in to using
CodeMirror, we make the existing 'usecodemirror' option into a visible
preference. In addition, with two preferences related to CodeMirror, we
group them under a new heading 'Syntax highlighting'. More preferences
may be added later to this section following T359498.
When WikiEditor is not enabled, the layout of the action=edit page has
the textarea as a sibling to other visible content, like `.editOptions`.
Because of this, we can't simply append the CodeMirror DOM to the parent
like we were before, as that would put the visible editor beneath the
edit summary, Publish button, etc. Instead we rework the CodeMirror to
first add a wrapper around the textarea and use that as the parent. This
way, `.cm-editor` is always in the same place in the DOM as the native
textarea.
Line wrapping and focus/blur events are also moved to CodeMirror, as
these are needed when not using WikiEditor.
Bug: T190108
Change-Id: I4bc069e0d398aa7088e4f50bbd0ddda458b289c3
2024-03-26 20:40:13 +00:00
|
|
|
EditorView.domEventHandlers( {
|
2024-04-10 15:54:37 +00:00
|
|
|
blur: () => {
|
|
|
|
this.$textarea[ 0 ].dispatchEvent( new Event( 'blur' ) );
|
|
|
|
},
|
|
|
|
focus: () => {
|
|
|
|
this.$textarea[ 0 ].dispatchEvent( new Event( 'focus' ) );
|
|
|
|
}
|
CM6: Add syntax highlighting preference for users without WikiEditor
This adds the `ext.CodeMirror.v6.init` ResourceLoader module which
allows use of CodeMirror on `#wpTextbox1` without the use of WikiEditor
(the 'usebetatoolbar' preference). In order for users to opt-in to using
CodeMirror, we make the existing 'usecodemirror' option into a visible
preference. In addition, with two preferences related to CodeMirror, we
group them under a new heading 'Syntax highlighting'. More preferences
may be added later to this section following T359498.
When WikiEditor is not enabled, the layout of the action=edit page has
the textarea as a sibling to other visible content, like `.editOptions`.
Because of this, we can't simply append the CodeMirror DOM to the parent
like we were before, as that would put the visible editor beneath the
edit summary, Publish button, etc. Instead we rework the CodeMirror to
first add a wrapper around the textarea and use that as the parent. This
way, `.cm-editor` is always in the same place in the DOM as the native
textarea.
Line wrapping and focus/blur events are also moved to CodeMirror, as
these are needed when not using WikiEditor.
Bug: T190108
Change-Id: I4bc069e0d398aa7088e4f50bbd0ddda458b289c3
2024-03-26 20:40:13 +00:00
|
|
|
} ),
|
2024-08-01 21:39:43 +00:00
|
|
|
keymap.of( defaultKeymap ),
|
2024-03-11 21:03:28 +00:00
|
|
|
EditorState.allowMultipleSelections.of( true ),
|
2024-05-03 08:34:50 +00:00
|
|
|
drawSelection(),
|
|
|
|
rectangularSelection(),
|
|
|
|
crosshairCursor()
|
2023-10-11 02:00:08 +00:00
|
|
|
];
|
2024-03-11 21:34:36 +00:00
|
|
|
|
2024-03-11 21:03:28 +00:00
|
|
|
// Add extensions relevant to editing (not read-only).
|
|
|
|
if ( !this.readOnly ) {
|
|
|
|
extensions.push( EditorView.updateListener.of( ( update ) => {
|
|
|
|
if ( update.docChanged && typeof this.editRecoveryHandler === 'function' ) {
|
|
|
|
this.editRecoveryHandler();
|
|
|
|
}
|
|
|
|
} ) );
|
|
|
|
extensions.push( history() );
|
2024-05-24 21:20:04 +00:00
|
|
|
extensions.push( keymap.of(
|
|
|
|
historyKeymap.concat( /** @type {KeyBinding} */ {
|
|
|
|
win: 'Ctrl-Shift-z',
|
|
|
|
run: redo,
|
|
|
|
preventDefault: true
|
|
|
|
} )
|
|
|
|
) );
|
2024-03-11 21:03:28 +00:00
|
|
|
}
|
|
|
|
|
2023-09-19 17:59:29 +00:00
|
|
|
return extensions;
|
|
|
|
}
|
|
|
|
|
CodeMirrorPreferences: add panel to tweak prefs with the editor open
This is toggled by pressing Mod-Shift-, (or Command-Shift-, on MacOS),
which then puts focus on the preferences panel. It can be closed with
the Escape key, just like other CM panels.
The CodeMirror class comes with these extension which can be toggled in
preferences:
* Bracket matching
* Line numbering
* Line wrapping
* Highlight the active line
* Show special characters
Only bracket matching, line numbering, and line wrapping are available
in the 2017 editor.
The bidi isolation and template folding extensions are registered in
CodeMirrorModeMediaWiki as they are MW-specific. CodeMirrorPreferences'
new registerExtension() method allows any consumer of CodeMirror to add
any arbitrary extensions to the preferences panel. This is expected to
be called *after* CodeMirror has finished initializing. The
'ext.CodeMirror.ready' hook now passes the CodeMirror instance to
accommodate this.
The preferences are stored as a single user option in the database,
called 'codemirror-preferences'. The defaults can be configured with the
$wgCodeMirrorDefaultPreferences configuration setting. The
sysadmin-facing values are the familiar boolean, but since CodeMirror is
widely used, we make extra efforts to reduce the storage footprint (see
T54777). This includes only storing preferences that differ from the
defaults, and using binary representation instead of boolean values,
since the user option is stored as a string.
For now, all preferences are ignored in the 2017 editor. In a future
patch, we may add some as toggleable Tools in the VE toolbar.
Other changes:
* Refactor CSS to use a .darkmode() mixin
* Add a method to create a CSS-only fieldset in CodeMirrorPanel
* Fix Jest tests now that there are more calls to mw.user.options.get()
* Adjust Selenium tests to always use CM6
* Adjust Selenium tests to delete test pages (useful for local dev)
* Remove unused code
Bug: T359498
Change-Id: I70dcf2f49418cea632c452c1266440effad634f3
2024-08-16 01:52:13 +00:00
|
|
|
/**
|
|
|
|
* Extension for highlighting the active line.
|
|
|
|
*
|
|
|
|
* @return {Extension}
|
|
|
|
*/
|
|
|
|
get activeLineExtension() {
|
|
|
|
return highlightActiveLine();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extension for line wrapping.
|
|
|
|
*
|
|
|
|
* @return {Extension}
|
|
|
|
*/
|
|
|
|
get lineWrappingExtension() {
|
|
|
|
return EditorView.lineWrapping;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extension for line numbering.
|
|
|
|
*
|
|
|
|
* @return {Extension|Extension[]}
|
|
|
|
*/
|
|
|
|
get lineNumberingExtension() {
|
|
|
|
return lineNumbers();
|
|
|
|
}
|
|
|
|
|
2024-08-01 21:39:43 +00:00
|
|
|
/**
|
|
|
|
* Extension for search and goto line functionality.
|
|
|
|
*
|
|
|
|
* @return {Extension|Extension[]}
|
|
|
|
*/
|
|
|
|
get searchExtension() {
|
|
|
|
return [
|
|
|
|
new CodeMirrorSearch().extension,
|
|
|
|
new CodeMirrorGotoLine().extension
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2024-04-19 19:26:38 +00:00
|
|
|
/**
|
|
|
|
* This extension adds bracket matching to the CodeMirror editor.
|
|
|
|
*
|
|
|
|
* @return {Extension}
|
|
|
|
*/
|
|
|
|
get bracketMatchingExtension() {
|
|
|
|
return bracketMatching( mw.config.get( 'wgPageContentModel' ) === 'wikitext' ?
|
|
|
|
{
|
|
|
|
// Also match CJK full-width brackets (T362992)
|
|
|
|
// This is only for wikitext as it can be confusing in programming languages.
|
|
|
|
brackets: '()[]{}()【】[]{}'
|
|
|
|
} : {}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-04-15 17:30:49 +00:00
|
|
|
/**
|
|
|
|
* This extension listens for changes in the CodeMirror editor and fires
|
|
|
|
* the `ext.CodeMirror.input` hook with the {@link ViewUpdate} object.
|
|
|
|
*
|
|
|
|
* @type {Extension}
|
|
|
|
* @fires CodeMirror~'ext.CodeMirror.input'
|
|
|
|
* @stable to call and override
|
|
|
|
*/
|
|
|
|
get updateExtension() {
|
|
|
|
return EditorView.updateListener.of( ( update ) => {
|
|
|
|
if ( update.docChanged ) {
|
|
|
|
/**
|
|
|
|
* Called when document changes are made in CodeMirror.
|
|
|
|
* The native textarea is not necessarily updated yet.
|
|
|
|
*
|
|
|
|
* @event CodeMirror~'ext.CodeMirror.input'
|
|
|
|
* @param {ViewUpdate} update
|
|
|
|
* @stable to use
|
|
|
|
*/
|
|
|
|
mw.hook( 'ext.CodeMirror.input' ).fire( update );
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
2024-02-28 05:14:04 +00:00
|
|
|
/**
|
|
|
|
* This extension sets the height of the CodeMirror editor to match the textarea.
|
|
|
|
* Override this method to change the height of the editor.
|
|
|
|
*
|
2024-03-19 03:10:11 +00:00
|
|
|
* @type {Extension}
|
|
|
|
* @stable to call and override
|
2024-02-28 05:14:04 +00:00
|
|
|
*/
|
|
|
|
get heightExtension() {
|
|
|
|
return EditorView.theme( {
|
|
|
|
'&': {
|
2024-06-08 03:10:11 +00:00
|
|
|
height: this.surface ? '100%' : `${ this.$textarea.outerHeight() }px`
|
2024-02-28 05:14:04 +00:00
|
|
|
},
|
|
|
|
'.cm-scroller': {
|
|
|
|
overflow: 'auto'
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
2023-10-11 02:00:08 +00:00
|
|
|
/**
|
2024-03-19 03:10:11 +00:00
|
|
|
* This specifies which attributes get added to the `.cm-content` and `.cm-editor` elements.
|
2023-12-06 18:46:59 +00:00
|
|
|
* Subclasses are safe to override this method, but attributes here are considered vital.
|
2023-10-11 02:00:08 +00:00
|
|
|
*
|
|
|
|
* @see https://codemirror.net/docs/ref/#view.EditorView^contentAttributes
|
2024-03-19 03:10:11 +00:00
|
|
|
* @type {Extension}
|
|
|
|
* @stable to call and override
|
2023-10-11 02:00:08 +00:00
|
|
|
*/
|
|
|
|
get contentAttributesExtension() {
|
2024-02-20 20:59:21 +00:00
|
|
|
const classList = [];
|
2024-06-08 03:10:11 +00:00
|
|
|
// T245568: Sync text editor font preferences with CodeMirror,
|
|
|
|
// but don't do this for the 2017 wikitext editor.
|
|
|
|
if ( !this.surface ) {
|
|
|
|
const fontClass = Array.from( this.$textarea[ 0 ].classList )
|
|
|
|
.find( ( style ) => style.startsWith( 'mw-editfont-' ) );
|
|
|
|
if ( fontClass ) {
|
|
|
|
classList.push( fontClass );
|
|
|
|
}
|
|
|
|
// Add colorblind mode if preference is set.
|
|
|
|
// This currently is only to be used for the MediaWiki markup language.
|
|
|
|
if (
|
|
|
|
mw.user.options.get( 'usecodemirror-colorblind' ) &&
|
|
|
|
mw.config.get( 'wgPageContentModel' ) === 'wikitext'
|
|
|
|
) {
|
|
|
|
classList.push( 'cm-mw-colorblind-colors' );
|
|
|
|
}
|
2024-02-20 20:59:21 +00:00
|
|
|
}
|
|
|
|
|
2024-03-08 01:36:15 +00:00
|
|
|
return [
|
|
|
|
// .cm-content element (the contenteditable area)
|
|
|
|
EditorView.contentAttributes.of( {
|
|
|
|
// T259347: Use accesskey of the original textbox
|
|
|
|
accesskey: this.$textarea.attr( 'accesskey' ),
|
|
|
|
// Classes need to be on .cm-content to have precedence over .cm-scroller
|
2024-03-11 21:03:28 +00:00
|
|
|
class: classList.join( ' ' ),
|
2024-03-21 01:51:09 +00:00
|
|
|
spellcheck: 'true',
|
|
|
|
tabindex: this.$textarea.attr( 'tabindex' )
|
2024-03-08 01:36:15 +00:00
|
|
|
} ),
|
|
|
|
// .cm-editor element (contains the whole CodeMirror UI)
|
|
|
|
EditorView.editorAttributes.of( {
|
2024-06-08 03:10:11 +00:00
|
|
|
// Use language of the original textbox.
|
2024-03-08 01:36:15 +00:00
|
|
|
// These should be attributes of .cm-editor, not the .cm-content (T359589)
|
|
|
|
lang: this.$textarea.attr( 'lang' )
|
2024-03-26 00:00:26 +00:00
|
|
|
} ),
|
2024-04-15 00:05:56 +00:00
|
|
|
// The search panel should use the same direction as the interface language (T359611)
|
2024-03-26 00:00:26 +00:00
|
|
|
EditorView.theme( {
|
|
|
|
'.cm-panels': {
|
|
|
|
direction: document.dir
|
|
|
|
}
|
2024-03-08 01:36:15 +00:00
|
|
|
} )
|
|
|
|
];
|
2023-10-11 02:00:08 +00:00
|
|
|
}
|
|
|
|
|
2024-01-13 03:21:12 +00:00
|
|
|
/**
|
|
|
|
* These are all potential messages used in a full-featured CodeMirror setup.
|
|
|
|
* We lump them all here and supply it as default extensions because it is only a small cost
|
|
|
|
* and we don't want localization to be overlooked by CodeMirror clients and subclasses.
|
|
|
|
*
|
|
|
|
* @see https://codemirror.net/examples/translate/
|
2024-03-19 03:10:11 +00:00
|
|
|
* @type {Extension}
|
|
|
|
* @stable to call. Instead of overriding, pass in an additional `EditorState.phrases.of()`
|
|
|
|
* when calling `initialize()`.
|
2024-01-13 03:21:12 +00:00
|
|
|
*/
|
|
|
|
get phrasesExtension() {
|
|
|
|
return EditorState.phrases.of( {
|
2024-01-19 00:33:58 +00:00
|
|
|
'Control character': mw.msg( 'codemirror-control-character' )
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* We give a small subset of special characters a tooltip explaining what they are.
|
|
|
|
* The messages and for what characters are defined here.
|
|
|
|
* Any character that does not have a message will instead use CM6 defaults,
|
|
|
|
* which is the localization of 'codemirror-control-character' followed by the Unicode number.
|
|
|
|
*
|
|
|
|
* @see https://codemirror.net/docs/ref/#view.highlightSpecialChars
|
2024-03-19 03:10:11 +00:00
|
|
|
* @type {Extension}
|
|
|
|
* @stable to call
|
2024-01-19 00:33:58 +00:00
|
|
|
*/
|
|
|
|
get specialCharsExtension() {
|
CodeMirrorPreferences: add panel to tweak prefs with the editor open
This is toggled by pressing Mod-Shift-, (or Command-Shift-, on MacOS),
which then puts focus on the preferences panel. It can be closed with
the Escape key, just like other CM panels.
The CodeMirror class comes with these extension which can be toggled in
preferences:
* Bracket matching
* Line numbering
* Line wrapping
* Highlight the active line
* Show special characters
Only bracket matching, line numbering, and line wrapping are available
in the 2017 editor.
The bidi isolation and template folding extensions are registered in
CodeMirrorModeMediaWiki as they are MW-specific. CodeMirrorPreferences'
new registerExtension() method allows any consumer of CodeMirror to add
any arbitrary extensions to the preferences panel. This is expected to
be called *after* CodeMirror has finished initializing. The
'ext.CodeMirror.ready' hook now passes the CodeMirror instance to
accommodate this.
The preferences are stored as a single user option in the database,
called 'codemirror-preferences'. The defaults can be configured with the
$wgCodeMirrorDefaultPreferences configuration setting. The
sysadmin-facing values are the familiar boolean, but since CodeMirror is
widely used, we make extra efforts to reduce the storage footprint (see
T54777). This includes only storing preferences that differ from the
defaults, and using binary representation instead of boolean values,
since the user option is stored as a string.
For now, all preferences are ignored in the 2017 editor. In a future
patch, we may add some as toggleable Tools in the VE toolbar.
Other changes:
* Refactor CSS to use a .darkmode() mixin
* Add a method to create a CSS-only fieldset in CodeMirrorPanel
* Fix Jest tests now that there are more calls to mw.user.options.get()
* Adjust Selenium tests to always use CM6
* Adjust Selenium tests to delete test pages (useful for local dev)
* Remove unused code
Bug: T359498
Change-Id: I70dcf2f49418cea632c452c1266440effad634f3
2024-08-16 01:52:13 +00:00
|
|
|
// Keys are the decimal Unicode number, values are the messages.
|
2024-01-19 00:33:58 +00:00
|
|
|
const messages = {
|
|
|
|
0: mw.msg( 'codemirror-special-char-null' ),
|
|
|
|
7: mw.msg( 'codemirror-special-char-bell' ),
|
|
|
|
8: mw.msg( 'codemirror-special-char-backspace' ),
|
|
|
|
10: mw.msg( 'codemirror-special-char-newline' ),
|
|
|
|
11: mw.msg( 'codemirror-special-char-vertical-tab' ),
|
|
|
|
13: mw.msg( 'codemirror-special-char-carriage-return' ),
|
|
|
|
27: mw.msg( 'codemirror-special-char-escape' ),
|
|
|
|
160: mw.msg( 'codemirror-special-char-nbsp' ),
|
|
|
|
8203: mw.msg( 'codemirror-special-char-zero-width-space' ),
|
|
|
|
8204: mw.msg( 'codemirror-special-char-zero-width-non-joiner' ),
|
|
|
|
8205: mw.msg( 'codemirror-special-char-zero-width-joiner' ),
|
|
|
|
8206: mw.msg( 'codemirror-special-char-left-to-right-mark' ),
|
|
|
|
8207: mw.msg( 'codemirror-special-char-right-to-left-mark' ),
|
|
|
|
8232: mw.msg( 'codemirror-special-char-line-separator' ),
|
|
|
|
8237: mw.msg( 'codemirror-special-char-left-to-right-override' ),
|
|
|
|
8238: mw.msg( 'codemirror-special-char-right-to-left-override' ),
|
|
|
|
8239: mw.msg( 'codemirror-special-char-narrow-nbsp' ),
|
|
|
|
8294: mw.msg( 'codemirror-special-char-left-to-right-isolate' ),
|
|
|
|
8295: mw.msg( 'codemirror-special-char-right-to-left-isolate' ),
|
|
|
|
8297: mw.msg( 'codemirror-special-char-pop-directional-isolate' ),
|
|
|
|
8233: mw.msg( 'codemirror-special-char-paragraph-separator' ),
|
|
|
|
65279: mw.msg( 'codemirror-special-char-zero-width-no-break-space' ),
|
|
|
|
65532: mw.msg( 'codemirror-special-char-object-replacement' )
|
|
|
|
};
|
|
|
|
|
|
|
|
return highlightSpecialChars( {
|
|
|
|
render: ( code, description, placeholder ) => {
|
|
|
|
description = messages[ code ] || mw.msg( 'codemirror-control-character', code );
|
|
|
|
const span = document.createElement( 'span' );
|
|
|
|
span.className = 'cm-specialChar';
|
|
|
|
|
|
|
|
// Special case non-breaking spaces (T181677).
|
|
|
|
if ( code === 160 || code === 8239 ) {
|
|
|
|
placeholder = '·';
|
|
|
|
span.className = 'cm-special-char-nbsp';
|
|
|
|
}
|
|
|
|
|
|
|
|
span.textContent = placeholder;
|
|
|
|
span.title = description;
|
|
|
|
span.setAttribute( 'aria-label', description );
|
|
|
|
return span;
|
|
|
|
},
|
|
|
|
// Highlight non-breaking spaces (T181677)
|
2024-03-11 21:03:28 +00:00
|
|
|
addSpecialChars: /[\u00a0\u202f]/g
|
2024-01-13 03:21:12 +00:00
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
CodeMirrorPreferences: add panel to tweak prefs with the editor open
This is toggled by pressing Mod-Shift-, (or Command-Shift-, on MacOS),
which then puts focus on the preferences panel. It can be closed with
the Escape key, just like other CM panels.
The CodeMirror class comes with these extension which can be toggled in
preferences:
* Bracket matching
* Line numbering
* Line wrapping
* Highlight the active line
* Show special characters
Only bracket matching, line numbering, and line wrapping are available
in the 2017 editor.
The bidi isolation and template folding extensions are registered in
CodeMirrorModeMediaWiki as they are MW-specific. CodeMirrorPreferences'
new registerExtension() method allows any consumer of CodeMirror to add
any arbitrary extensions to the preferences panel. This is expected to
be called *after* CodeMirror has finished initializing. The
'ext.CodeMirror.ready' hook now passes the CodeMirror instance to
accommodate this.
The preferences are stored as a single user option in the database,
called 'codemirror-preferences'. The defaults can be configured with the
$wgCodeMirrorDefaultPreferences configuration setting. The
sysadmin-facing values are the familiar boolean, but since CodeMirror is
widely used, we make extra efforts to reduce the storage footprint (see
T54777). This includes only storing preferences that differ from the
defaults, and using binary representation instead of boolean values,
since the user option is stored as a string.
For now, all preferences are ignored in the 2017 editor. In a future
patch, we may add some as toggleable Tools in the VE toolbar.
Other changes:
* Refactor CSS to use a .darkmode() mixin
* Add a method to create a CSS-only fieldset in CodeMirrorPanel
* Fix Jest tests now that there are more calls to mw.user.options.get()
* Adjust Selenium tests to always use CM6
* Adjust Selenium tests to delete test pages (useful for local dev)
* Remove unused code
Bug: T359498
Change-Id: I70dcf2f49418cea632c452c1266440effad634f3
2024-08-16 01:52:13 +00:00
|
|
|
/**
|
|
|
|
* This extension adds the ability to change the direction of the editor.
|
|
|
|
*
|
|
|
|
* @type {Extension}
|
|
|
|
* @stable to call
|
|
|
|
*/
|
2024-06-08 03:10:11 +00:00
|
|
|
get dirExtension() {
|
|
|
|
return [
|
|
|
|
this.dirCompartment.of( EditorView.editorAttributes.of( {
|
|
|
|
// Use direction of the original textbox.
|
|
|
|
// These should be attributes of .cm-editor, not the .cm-content (T359589)
|
|
|
|
dir: this.$textarea.attr( 'dir' )
|
|
|
|
} ) ),
|
|
|
|
keymap.of( [ {
|
|
|
|
key: 'Mod-Shift-x',
|
|
|
|
run: ( view ) => {
|
|
|
|
const dir = this.$textarea.attr( 'dir' ) === 'rtl' ? 'ltr' : 'rtl';
|
|
|
|
this.$textarea.attr( 'dir', dir );
|
|
|
|
view.dispatch( {
|
|
|
|
effects: this.dirCompartment.reconfigure(
|
|
|
|
EditorView.editorAttributes.of( { dir } )
|
|
|
|
)
|
|
|
|
} );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} ] )
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2023-09-19 17:59:29 +00:00
|
|
|
/**
|
|
|
|
* Setup CodeMirror and add it to the DOM. This will hide the original textarea.
|
|
|
|
*
|
2024-03-19 03:10:11 +00:00
|
|
|
* @param {Extension|Extension[]} [extensions=this.defaultExtensions] Extensions to use.
|
|
|
|
* @fires CodeMirror~'ext.CodeMirror.initialize'
|
2024-03-20 00:58:50 +00:00
|
|
|
* @fires CodeMirror~'ext.CodeMirror.ready'
|
2024-03-19 03:10:11 +00:00
|
|
|
* @stable to call and override
|
2023-09-19 17:59:29 +00:00
|
|
|
*/
|
|
|
|
initialize( extensions = this.defaultExtensions ) {
|
2024-03-19 03:10:11 +00:00
|
|
|
/**
|
|
|
|
* Called just before CodeMirror is initialized.
|
|
|
|
* This can be used to manipulate the DOM to suit CodeMirror
|
|
|
|
* (i.e. if you manipulate WikiEditor's DOM, you may need this).
|
|
|
|
*
|
|
|
|
* @event CodeMirror~'ext.CodeMirror.initialize'
|
|
|
|
* @param {jQuery} $textarea The textarea that CodeMirror is bound to.
|
|
|
|
* @stable to use
|
|
|
|
*/
|
2024-02-22 21:18:41 +00:00
|
|
|
mw.hook( 'ext.CodeMirror.initialize' ).fire( this.$textarea );
|
2024-03-11 21:03:28 +00:00
|
|
|
mw.hook( 'editRecovery.loadEnd' ).add( ( data ) => {
|
|
|
|
this.editRecoveryHandler = data.fieldChangeHandler;
|
|
|
|
} );
|
2024-02-22 21:18:41 +00:00
|
|
|
|
2023-09-19 17:59:29 +00:00
|
|
|
// Set up the initial EditorState of CodeMirror with contents of the native textarea.
|
|
|
|
this.state = EditorState.create( {
|
2024-06-08 03:10:11 +00:00
|
|
|
doc: this.surface ?
|
|
|
|
this.surface.getDom() :
|
|
|
|
this.$textarea.textSelection( 'getContents' ),
|
2023-09-19 17:59:29 +00:00
|
|
|
extensions
|
|
|
|
} );
|
|
|
|
|
|
|
|
// Add CodeMirror view to the DOM.
|
Isolate build step to CM6 library and restructure files to work with RL
CodeMirror 6 requires the use of NPM, but we can still bundle all CM
packages into one file, and then everything else (i.e. our code) is
managed by ResourceLoader as per usual. This makes contribution
considerably easier as we no longer need a build step for each change.
CM5 files are now under resources/legacy, and the CM6 files are moved to
the root of the resources/ directory. Only one file,
codemirror.bundle.js, is managed by Rollup, while everything else is RL.
The Rollup output for now is put under resources/lib/ alongside the CM5
upstream files.
This patch is *mostly* renames of files, along with changing ECMAScript
Module (ESM) syntax into the CommonJS style that ResourceLoader prefers.
We also remove more modern JS syntax (i.e. private class methods) that
we were able to use before because we had a build step with Babel.
This patch should effectively make no user-facing changes, or to the
ResourceLoader modules we offer in Extension:CodeMirror.
Finally, bump version in extension.json to 6, to match the upstream lib,
and add Bhsd as an author :-)
Bug: T368053
Change-Id: Ie258e49f5df8db23a7344ac3c4c9300aaa991042
2024-06-21 03:21:09 +00:00
|
|
|
this.addCodeMirrorToDom();
|
2023-09-19 17:59:29 +00:00
|
|
|
|
|
|
|
// Hide native textarea and sync CodeMirror contents upon submission.
|
2024-06-08 03:10:11 +00:00
|
|
|
if ( !this.surface ) {
|
|
|
|
this.$textarea.hide();
|
|
|
|
if ( this.$textarea[ 0 ].form ) {
|
2024-12-04 05:03:39 +00:00
|
|
|
this.formSubmitEventHandler = () => {
|
2024-06-08 03:10:11 +00:00
|
|
|
this.$textarea.val( this.view.state.doc.toString() );
|
|
|
|
const scrollTop = document.getElementById( 'wpScrolltop' );
|
|
|
|
if ( scrollTop ) {
|
|
|
|
scrollTop.value = this.view.scrollDOM.scrollTop;
|
|
|
|
}
|
2024-12-04 05:03:39 +00:00
|
|
|
};
|
|
|
|
this.$textarea[ 0 ].form.addEventListener( 'submit', this.formSubmitEventHandler );
|
2024-06-08 03:10:11 +00:00
|
|
|
}
|
2023-09-19 17:59:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Register $.textSelection() on the .cm-editor element.
|
|
|
|
$( this.view.dom ).textSelection( 'register', this.cmTextSelection );
|
|
|
|
// Also override textSelection() functions for the "real" hidden textarea to route to
|
|
|
|
// CodeMirror. We unregister this when switching to normal textarea mode.
|
|
|
|
this.$textarea.textSelection( 'register', this.cmTextSelection );
|
2024-03-20 00:58:50 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Called just after CodeMirror is initialized.
|
|
|
|
*
|
|
|
|
* @event CodeMirror~'ext.CodeMirror.ready'
|
CodeMirrorPreferences: add panel to tweak prefs with the editor open
This is toggled by pressing Mod-Shift-, (or Command-Shift-, on MacOS),
which then puts focus on the preferences panel. It can be closed with
the Escape key, just like other CM panels.
The CodeMirror class comes with these extension which can be toggled in
preferences:
* Bracket matching
* Line numbering
* Line wrapping
* Highlight the active line
* Show special characters
Only bracket matching, line numbering, and line wrapping are available
in the 2017 editor.
The bidi isolation and template folding extensions are registered in
CodeMirrorModeMediaWiki as they are MW-specific. CodeMirrorPreferences'
new registerExtension() method allows any consumer of CodeMirror to add
any arbitrary extensions to the preferences panel. This is expected to
be called *after* CodeMirror has finished initializing. The
'ext.CodeMirror.ready' hook now passes the CodeMirror instance to
accommodate this.
The preferences are stored as a single user option in the database,
called 'codemirror-preferences'. The defaults can be configured with the
$wgCodeMirrorDefaultPreferences configuration setting. The
sysadmin-facing values are the familiar boolean, but since CodeMirror is
widely used, we make extra efforts to reduce the storage footprint (see
T54777). This includes only storing preferences that differ from the
defaults, and using binary representation instead of boolean values,
since the user option is stored as a string.
For now, all preferences are ignored in the 2017 editor. In a future
patch, we may add some as toggleable Tools in the VE toolbar.
Other changes:
* Refactor CSS to use a .darkmode() mixin
* Add a method to create a CSS-only fieldset in CodeMirrorPanel
* Fix Jest tests now that there are more calls to mw.user.options.get()
* Adjust Selenium tests to always use CM6
* Adjust Selenium tests to delete test pages (useful for local dev)
* Remove unused code
Bug: T359498
Change-Id: I70dcf2f49418cea632c452c1266440effad634f3
2024-08-16 01:52:13 +00:00
|
|
|
* @param {jQuery} $view The CodeMirror view element.
|
2024-12-10 05:33:03 +00:00
|
|
|
* @param {CodeMirror} cm The CodeMirror instance.
|
2024-03-20 00:58:50 +00:00
|
|
|
* @stable to use
|
|
|
|
*/
|
CodeMirrorPreferences: add panel to tweak prefs with the editor open
This is toggled by pressing Mod-Shift-, (or Command-Shift-, on MacOS),
which then puts focus on the preferences panel. It can be closed with
the Escape key, just like other CM panels.
The CodeMirror class comes with these extension which can be toggled in
preferences:
* Bracket matching
* Line numbering
* Line wrapping
* Highlight the active line
* Show special characters
Only bracket matching, line numbering, and line wrapping are available
in the 2017 editor.
The bidi isolation and template folding extensions are registered in
CodeMirrorModeMediaWiki as they are MW-specific. CodeMirrorPreferences'
new registerExtension() method allows any consumer of CodeMirror to add
any arbitrary extensions to the preferences panel. This is expected to
be called *after* CodeMirror has finished initializing. The
'ext.CodeMirror.ready' hook now passes the CodeMirror instance to
accommodate this.
The preferences are stored as a single user option in the database,
called 'codemirror-preferences'. The defaults can be configured with the
$wgCodeMirrorDefaultPreferences configuration setting. The
sysadmin-facing values are the familiar boolean, but since CodeMirror is
widely used, we make extra efforts to reduce the storage footprint (see
T54777). This includes only storing preferences that differ from the
defaults, and using binary representation instead of boolean values,
since the user option is stored as a string.
For now, all preferences are ignored in the 2017 editor. In a future
patch, we may add some as toggleable Tools in the VE toolbar.
Other changes:
* Refactor CSS to use a .darkmode() mixin
* Add a method to create a CSS-only fieldset in CodeMirrorPanel
* Fix Jest tests now that there are more calls to mw.user.options.get()
* Adjust Selenium tests to always use CM6
* Adjust Selenium tests to delete test pages (useful for local dev)
* Remove unused code
Bug: T359498
Change-Id: I70dcf2f49418cea632c452c1266440effad634f3
2024-08-16 01:52:13 +00:00
|
|
|
mw.hook( 'ext.CodeMirror.ready' ).fire( $( this.view.dom ), this );
|
2024-03-20 00:58:50 +00:00
|
|
|
}
|
|
|
|
|
CM6: Add syntax highlighting preference for users without WikiEditor
This adds the `ext.CodeMirror.v6.init` ResourceLoader module which
allows use of CodeMirror on `#wpTextbox1` without the use of WikiEditor
(the 'usebetatoolbar' preference). In order for users to opt-in to using
CodeMirror, we make the existing 'usecodemirror' option into a visible
preference. In addition, with two preferences related to CodeMirror, we
group them under a new heading 'Syntax highlighting'. More preferences
may be added later to this section following T359498.
When WikiEditor is not enabled, the layout of the action=edit page has
the textarea as a sibling to other visible content, like `.editOptions`.
Because of this, we can't simply append the CodeMirror DOM to the parent
like we were before, as that would put the visible editor beneath the
edit summary, Publish button, etc. Instead we rework the CodeMirror to
first add a wrapper around the textarea and use that as the parent. This
way, `.cm-editor` is always in the same place in the DOM as the native
textarea.
Line wrapping and focus/blur events are also moved to CodeMirror, as
these are needed when not using WikiEditor.
Bug: T190108
Change-Id: I4bc069e0d398aa7088e4f50bbd0ddda458b289c3
2024-03-26 20:40:13 +00:00
|
|
|
/**
|
|
|
|
* Instantiate the EditorView, adding the CodeMirror editor to the DOM.
|
|
|
|
* We use a dummy container to ensure that the editor will
|
|
|
|
* always be placed where the textarea is.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
*/
|
Isolate build step to CM6 library and restructure files to work with RL
CodeMirror 6 requires the use of NPM, but we can still bundle all CM
packages into one file, and then everything else (i.e. our code) is
managed by ResourceLoader as per usual. This makes contribution
considerably easier as we no longer need a build step for each change.
CM5 files are now under resources/legacy, and the CM6 files are moved to
the root of the resources/ directory. Only one file,
codemirror.bundle.js, is managed by Rollup, while everything else is RL.
The Rollup output for now is put under resources/lib/ alongside the CM5
upstream files.
This patch is *mostly* renames of files, along with changing ECMAScript
Module (ESM) syntax into the CommonJS style that ResourceLoader prefers.
We also remove more modern JS syntax (i.e. private class methods) that
we were able to use before because we had a build step with Babel.
This patch should effectively make no user-facing changes, or to the
ResourceLoader modules we offer in Extension:CodeMirror.
Finally, bump version in extension.json to 6, to match the upstream lib,
and add Bhsd as an author :-)
Bug: T368053
Change-Id: Ie258e49f5df8db23a7344ac3c4c9300aaa991042
2024-06-21 03:21:09 +00:00
|
|
|
addCodeMirrorToDom() {
|
CM6: Add syntax highlighting preference for users without WikiEditor
This adds the `ext.CodeMirror.v6.init` ResourceLoader module which
allows use of CodeMirror on `#wpTextbox1` without the use of WikiEditor
(the 'usebetatoolbar' preference). In order for users to opt-in to using
CodeMirror, we make the existing 'usecodemirror' option into a visible
preference. In addition, with two preferences related to CodeMirror, we
group them under a new heading 'Syntax highlighting'. More preferences
may be added later to this section following T359498.
When WikiEditor is not enabled, the layout of the action=edit page has
the textarea as a sibling to other visible content, like `.editOptions`.
Because of this, we can't simply append the CodeMirror DOM to the parent
like we were before, as that would put the visible editor beneath the
edit summary, Publish button, etc. Instead we rework the CodeMirror to
first add a wrapper around the textarea and use that as the parent. This
way, `.cm-editor` is always in the same place in the DOM as the native
textarea.
Line wrapping and focus/blur events are also moved to CodeMirror, as
these are needed when not using WikiEditor.
Bug: T190108
Change-Id: I4bc069e0d398aa7088e4f50bbd0ddda458b289c3
2024-03-26 20:40:13 +00:00
|
|
|
this.$textarea.wrap( '<div class="ext-codemirror-wrapper"></div>' );
|
|
|
|
|
|
|
|
this.view = new EditorView( {
|
|
|
|
state: this.state,
|
2024-06-08 03:10:11 +00:00
|
|
|
parent: this.surface ?
|
|
|
|
this.surface.getView().$element[ 0 ] :
|
|
|
|
this.$textarea.parent()[ 0 ]
|
CM6: Add syntax highlighting preference for users without WikiEditor
This adds the `ext.CodeMirror.v6.init` ResourceLoader module which
allows use of CodeMirror on `#wpTextbox1` without the use of WikiEditor
(the 'usebetatoolbar' preference). In order for users to opt-in to using
CodeMirror, we make the existing 'usecodemirror' option into a visible
preference. In addition, with two preferences related to CodeMirror, we
group them under a new heading 'Syntax highlighting'. More preferences
may be added later to this section following T359498.
When WikiEditor is not enabled, the layout of the action=edit page has
the textarea as a sibling to other visible content, like `.editOptions`.
Because of this, we can't simply append the CodeMirror DOM to the parent
like we were before, as that would put the visible editor beneath the
edit summary, Publish button, etc. Instead we rework the CodeMirror to
first add a wrapper around the textarea and use that as the parent. This
way, `.cm-editor` is always in the same place in the DOM as the native
textarea.
Line wrapping and focus/blur events are also moved to CodeMirror, as
these are needed when not using WikiEditor.
Bug: T190108
Change-Id: I4bc069e0d398aa7088e4f50bbd0ddda458b289c3
2024-03-26 20:40:13 +00:00
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
2024-03-20 00:58:50 +00:00
|
|
|
/**
|
|
|
|
* Destroy the CodeMirror instance and revert to the original textarea.
|
|
|
|
*
|
|
|
|
* @fires CodeMirror~'ext.CodeMirror.destroy'
|
|
|
|
* @stable to call and override
|
|
|
|
*/
|
|
|
|
destroy() {
|
|
|
|
const scrollTop = this.view.scrollDOM.scrollTop;
|
2024-12-04 05:03:39 +00:00
|
|
|
const hasFocus = this.surface ? this.surface.getView().isFocused() : this.view.hasFocus;
|
2024-03-20 00:58:50 +00:00
|
|
|
const { from, to } = this.view.state.selection.ranges[ 0 ];
|
|
|
|
$( this.view.dom ).textSelection( 'unregister' );
|
|
|
|
this.$textarea.textSelection( 'unregister' );
|
CM6: Add syntax highlighting preference for users without WikiEditor
This adds the `ext.CodeMirror.v6.init` ResourceLoader module which
allows use of CodeMirror on `#wpTextbox1` without the use of WikiEditor
(the 'usebetatoolbar' preference). In order for users to opt-in to using
CodeMirror, we make the existing 'usecodemirror' option into a visible
preference. In addition, with two preferences related to CodeMirror, we
group them under a new heading 'Syntax highlighting'. More preferences
may be added later to this section following T359498.
When WikiEditor is not enabled, the layout of the action=edit page has
the textarea as a sibling to other visible content, like `.editOptions`.
Because of this, we can't simply append the CodeMirror DOM to the parent
like we were before, as that would put the visible editor beneath the
edit summary, Publish button, etc. Instead we rework the CodeMirror to
first add a wrapper around the textarea and use that as the parent. This
way, `.cm-editor` is always in the same place in the DOM as the native
textarea.
Line wrapping and focus/blur events are also moved to CodeMirror, as
these are needed when not using WikiEditor.
Bug: T190108
Change-Id: I4bc069e0d398aa7088e4f50bbd0ddda458b289c3
2024-03-26 20:40:13 +00:00
|
|
|
this.$textarea.unwrap( '.ext-codemirror-wrapper' );
|
2024-06-08 03:10:11 +00:00
|
|
|
if ( !this.surface ) {
|
|
|
|
this.$textarea.val( this.view.state.doc.toString() );
|
|
|
|
}
|
2024-03-20 00:58:50 +00:00
|
|
|
this.view.destroy();
|
|
|
|
this.view = null;
|
|
|
|
this.$textarea.show();
|
|
|
|
if ( hasFocus ) {
|
|
|
|
this.$textarea.trigger( 'focus' );
|
|
|
|
}
|
|
|
|
this.$textarea.prop( 'selectionStart', Math.min( from, to ) )
|
|
|
|
.prop( 'selectionEnd', Math.max( to, from ) );
|
|
|
|
this.$textarea.scrollTop( scrollTop );
|
|
|
|
this.textSelection = null;
|
|
|
|
|
2024-12-04 05:03:39 +00:00
|
|
|
// remove all hook handlers and event listeners
|
|
|
|
if ( this.formSubmitEventHandler && this.$textarea[ 0 ].form ) {
|
|
|
|
this.$textarea[ 0 ].form.removeEventListener( 'submit', this.formSubmitEventHandler );
|
|
|
|
this.formSubmitEventHandler = null;
|
|
|
|
}
|
|
|
|
|
2024-03-20 00:58:50 +00:00
|
|
|
/**
|
|
|
|
* Called just after CodeMirror is destroyed and the original textarea is restored.
|
|
|
|
*
|
|
|
|
* @event CodeMirror~'ext.CodeMirror.destroy'
|
|
|
|
* @param {jQuery} $textarea The original textarea.
|
|
|
|
* @stable to use
|
|
|
|
*/
|
|
|
|
mw.hook( 'ext.CodeMirror.destroy' ).fire( this.$textarea );
|
2023-09-19 17:59:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Log usage of CodeMirror.
|
|
|
|
*
|
|
|
|
* @param {Object} data
|
2024-03-19 03:10:11 +00:00
|
|
|
* @stable to call
|
2024-06-08 03:10:11 +00:00
|
|
|
* @internal
|
|
|
|
* @ignore
|
2023-09-19 17:59:29 +00:00
|
|
|
*/
|
2024-06-08 03:10:11 +00:00
|
|
|
static logUsage( data ) {
|
2023-09-19 17:59:29 +00:00
|
|
|
/* eslint-disable camelcase */
|
|
|
|
const event = Object.assign( {
|
|
|
|
session_token: mw.user.sessionId(),
|
|
|
|
user_id: mw.user.getId()
|
|
|
|
}, data );
|
|
|
|
const editCountBucket = mw.config.get( 'wgUserEditCountBucket' );
|
|
|
|
if ( editCountBucket !== null ) {
|
|
|
|
event.user_edit_count_bucket = editCountBucket;
|
|
|
|
}
|
|
|
|
/* eslint-enable camelcase */
|
|
|
|
mw.track( 'event.CodeMirrorUsage', event );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Save CodeMirror enabled preference.
|
|
|
|
*
|
|
|
|
* @param {boolean} prefValue True, if CodeMirror should be enabled by default, otherwise false.
|
2024-03-19 03:10:11 +00:00
|
|
|
* @stable to call and override
|
2023-09-19 17:59:29 +00:00
|
|
|
*/
|
2024-06-08 03:10:11 +00:00
|
|
|
static setCodeMirrorPreference( prefValue ) {
|
2023-12-06 18:46:59 +00:00
|
|
|
// Skip for unnamed users
|
|
|
|
if ( !mw.user.isNamed() ) {
|
2023-09-19 17:59:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
new mw.Api().saveOption( 'usecodemirror', prefValue ? 1 : 0 );
|
|
|
|
mw.user.options.set( 'usecodemirror', prefValue ? 1 : 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* jQuery.textSelection overrides for CodeMirror.
|
|
|
|
*
|
2024-03-19 03:10:11 +00:00
|
|
|
* @see jQuery.fn.textSelection
|
|
|
|
* @type {Object}
|
|
|
|
* @private
|
2023-09-19 17:59:29 +00:00
|
|
|
*/
|
|
|
|
get cmTextSelection() {
|
2024-03-09 05:36:43 +00:00
|
|
|
if ( !this.textSelection ) {
|
2024-03-19 03:10:11 +00:00
|
|
|
this.textSelection = new CodeMirrorTextSelection( this.view );
|
2024-03-09 05:36:43 +00:00
|
|
|
}
|
2023-09-19 17:59:29 +00:00
|
|
|
return {
|
2024-03-09 05:36:43 +00:00
|
|
|
getContents: () => this.textSelection.getContents(),
|
|
|
|
setContents: ( content ) => this.textSelection.setContents( content ),
|
|
|
|
getCaretPosition: ( options ) => this.textSelection.getCaretPosition( options ),
|
|
|
|
scrollToCaretPosition: () => this.textSelection.scrollToCaretPosition(),
|
|
|
|
getSelection: () => this.textSelection.getSelection(),
|
|
|
|
setSelection: ( options ) => this.textSelection.setSelection( options ),
|
|
|
|
replaceSelection: ( value ) => this.textSelection.replaceSelection( value ),
|
|
|
|
encapsulateSelection: ( options ) => this.textSelection.encapsulateSelection( options )
|
2023-09-19 17:59:29 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
2024-03-19 03:10:11 +00:00
|
|
|
|
Isolate build step to CM6 library and restructure files to work with RL
CodeMirror 6 requires the use of NPM, but we can still bundle all CM
packages into one file, and then everything else (i.e. our code) is
managed by ResourceLoader as per usual. This makes contribution
considerably easier as we no longer need a build step for each change.
CM5 files are now under resources/legacy, and the CM6 files are moved to
the root of the resources/ directory. Only one file,
codemirror.bundle.js, is managed by Rollup, while everything else is RL.
The Rollup output for now is put under resources/lib/ alongside the CM5
upstream files.
This patch is *mostly* renames of files, along with changing ECMAScript
Module (ESM) syntax into the CommonJS style that ResourceLoader prefers.
We also remove more modern JS syntax (i.e. private class methods) that
we were able to use before because we had a build step with Babel.
This patch should effectively make no user-facing changes, or to the
ResourceLoader modules we offer in Extension:CodeMirror.
Finally, bump version in extension.json to 6, to match the upstream lib,
and add Bhsd as an author :-)
Bug: T368053
Change-Id: Ie258e49f5df8db23a7344ac3c4c9300aaa991042
2024-06-21 03:21:09 +00:00
|
|
|
module.exports = CodeMirror;
|