mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/CodeMirror
synced 2024-11-23 22:03:28 +00:00
CM6: add destroy method, fix removal of textSelection, add more hooks
CodeMirror is meant to be used without WikiEditor, so we add a destroy() method that does much the same things as CodeMirrorWikiEditor. The hooks added with this patch aren't used by anything yet, but offer feature parity with CodeMirrorWikiEditor, which fires the 'ext.CodeMirror.switch' hook. That hook can't be moved for backwards-compatibility reasons. The actual fix for T360075 here was to nullify the `textSelection` class property. Bug: T360075 Change-Id: Ife6a3f1ef90df66cd1bf8bab33c9ef3b39ed17a0
This commit is contained in:
parent
d652f3d2a2
commit
6be3bf62f0
2
resources/dist/codemirror.js
vendored
2
resources/dist/codemirror.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
"use strict";var e=require("ext.CodeMirror.v6.lib"),t=require("ext.CodeMirror.v6"),r=require("ext.CodeMirror.v6.mode.mediawiki"),i=function(t){function r(t,i){var o;return e._classCallCheck(this,r),(o=e._callSuper(this,r,[t])).langExtension=i,o.useCodeMirror=mw.user.options.get("usecodemirror")>0,o}return e._inherits(r,t),e._createClass(r,[{key:"setCodeMirrorPreference",value:function(t){this.useCodeMirror=t,e._get(e._getPrototypeOf(r.prototype),"setCodeMirrorPreference",this).call(this,t)}},{key:"enableCodeMirror",value:function(){var t=this;if(!this.view){var r=this.$textarea.prop("selectionStart"),i=this.$textarea.prop("selectionEnd"),o=this.$textarea.scrollTop(),s=this.$textarea.is(":focus"),a=[this.defaultExtensions,this.langExtension,e.EditorView.domEventHandlers({blur:function(){return t.$textarea.triggerHandler("blur")},focus:function(){return t.$textarea.triggerHandler("focus")}}),e.EditorView.lineWrapping];if(this.initialize(a),requestAnimationFrame((function(){t.view.scrollDOM.scrollTop=o})),0!==r||0!==i){var n=e.EditorSelection.range(r,i),d=e.EditorView.scrollIntoView(n);d.value.isSnapshot=!0,this.view.dispatch({selection:e.EditorSelection.create([n]),effects:d})}s&&this.view.focus(),mw.hook("ext.CodeMirror.switch").fire(!0,$(this.view.dom))}}},{key:"addCodeMirrorToWikiEditor",value:function(){var e=this,t=this.$textarea.data("wikiEditor-context"),r=t&&t.modules&&t.modules.toolbar;r&&(this.$textarea.wikiEditor("addToToolbar",{section:"main",groups:{codemirror:{tools:{CodeMirror:{label:mw.msg("codemirror-toggle-label"),type:"toggle",oouiIcon:"highlight",action:{type:"callback",execute:function(){return e.switchCodeMirror()}}}}}}}),r.$toolbar.find(".tool[rel=CodeMirror]").attr("id","mw-editbutton-codemirror"),this.readOnly&&this.$textarea.data("wikiEditor-context").$ui.addClass("ext-codemirror-readonly"),this.useCodeMirror&&this.enableCodeMirror(),this.updateToolbarButton(),this.logUsage({editor:"wikitext",enabled:this.useCodeMirror,toggled:!1,edit_start_ts_ms:1e3*parseInt($('input[name="wpStarttime"]').val(),10)||0}))}},{key:"updateToolbarButton",value:function(){var e=$("#mw-editbutton-codemirror");e.toggleClass("mw-editbutton-codemirror-active",this.useCodeMirror),e.data("setActive")&&e.data("setActive")(this.useCodeMirror)}},{key:"switchCodeMirror",value:function(){if(this.view){this.setCodeMirrorPreference(!1);var e=this.view.scrollDOM.scrollTop,t=this.view.hasFocus,r=this.view.state.selection.ranges[0],i=r.from,o=r.to;$(this.view.dom).textSelection("unregister"),this.$textarea.textSelection("unregister"),this.$textarea.val(this.view.state.doc.toString()),this.view.destroy(),this.view=null,this.$textarea.show(),t&&this.$textarea.trigger("focus"),this.$textarea.prop("selectionStart",Math.min(i,o)).prop("selectionEnd",Math.max(o,i)),this.$textarea.scrollTop(e),mw.hook("ext.CodeMirror.switch").fire(!1,this.$textarea)}else this.enableCodeMirror(),this.setCodeMirrorPreference(!0);this.updateToolbarButton(),this.logUsage({editor:"wikitext",enabled:this.useCodeMirror,toggled:!0,edit_start_ts_ms:1e3*parseInt($('input[name="wpStarttime"]').val(),10)||0})}}]),r}(t);mw.loader.getState("ext.wikiEditor")&&mw.hook("wikiEditor.toolbarReady").add((function(e){new i(e,r({bidiIsolation:"rtl"===e.attr("dir")})).addCodeMirrorToWikiEditor()}));
|
"use strict";var e=require("ext.CodeMirror.v6.lib"),t=require("ext.CodeMirror.v6"),r=require("ext.CodeMirror.v6.mode.mediawiki"),i=function(t){function r(t,i){var o;return e._classCallCheck(this,r),(o=e._callSuper(this,r,[t])).langExtension=i,o.useCodeMirror=mw.user.options.get("usecodemirror")>0,o}return e._inherits(r,t),e._createClass(r,[{key:"setCodeMirrorPreference",value:function(t){this.useCodeMirror=t,e._get(e._getPrototypeOf(r.prototype),"setCodeMirrorPreference",this).call(this,t)}},{key:"enableCodeMirror",value:function(){var t=this;if(!this.view){var r=this.$textarea.prop("selectionStart"),i=this.$textarea.prop("selectionEnd"),o=this.$textarea.scrollTop(),a=this.$textarea.is(":focus"),s=[this.defaultExtensions,this.langExtension,e.EditorView.domEventHandlers({blur:function(){return t.$textarea.triggerHandler("blur")},focus:function(){return t.$textarea.triggerHandler("focus")}}),e.EditorView.lineWrapping];if(this.initialize(s),requestAnimationFrame((function(){t.view.scrollDOM.scrollTop=o})),0!==r||0!==i){var d=e.EditorSelection.range(r,i),n=e.EditorView.scrollIntoView(d);n.value.isSnapshot=!0,this.view.dispatch({selection:e.EditorSelection.create([d]),effects:n})}a&&this.view.focus(),mw.hook("ext.CodeMirror.switch").fire(!0,$(this.view.dom))}}},{key:"addCodeMirrorToWikiEditor",value:function(){var e=this,t=this.$textarea.data("wikiEditor-context"),r=t&&t.modules&&t.modules.toolbar;r&&(this.$textarea.wikiEditor("addToToolbar",{section:"main",groups:{codemirror:{tools:{CodeMirror:{label:mw.msg("codemirror-toggle-label"),type:"toggle",oouiIcon:"highlight",action:{type:"callback",execute:function(){return e.switchCodeMirror()}}}}}}}),r.$toolbar.find(".tool[rel=CodeMirror]").attr("id","mw-editbutton-codemirror"),this.readOnly&&this.$textarea.data("wikiEditor-context").$ui.addClass("ext-codemirror-readonly"),this.useCodeMirror&&this.enableCodeMirror(),this.updateToolbarButton(),this.logUsage({editor:"wikitext",enabled:this.useCodeMirror,toggled:!1,edit_start_ts_ms:1e3*parseInt($('input[name="wpStarttime"]').val(),10)||0}))}},{key:"updateToolbarButton",value:function(){var e=$("#mw-editbutton-codemirror");e.toggleClass("mw-editbutton-codemirror-active",this.useCodeMirror),e.data("setActive")&&e.data("setActive")(this.useCodeMirror)}},{key:"switchCodeMirror",value:function(){this.view?(this.setCodeMirrorPreference(!1),this.destroy(),mw.hook("ext.CodeMirror.switch").fire(!1,this.$textarea)):(this.enableCodeMirror(),this.setCodeMirrorPreference(!0)),this.updateToolbarButton(),this.logUsage({editor:"wikitext",enabled:this.useCodeMirror,toggled:!0,edit_start_ts_ms:1e3*parseInt($('input[name="wpStarttime"]').val(),10)||0})}}]),r}(t);mw.loader.getState("ext.wikiEditor")&&mw.hook("wikiEditor.toolbarReady").add((function(e){new i(e,r({bidiIsolation:"rtl"===e.attr("dir")})).addCodeMirrorToWikiEditor()}));
|
||||||
|
|
|
@ -258,6 +258,7 @@ class CodeMirror {
|
||||||
*
|
*
|
||||||
* @param {Extension|Extension[]} [extensions=this.defaultExtensions] Extensions to use.
|
* @param {Extension|Extension[]} [extensions=this.defaultExtensions] Extensions to use.
|
||||||
* @fires CodeMirror~'ext.CodeMirror.initialize'
|
* @fires CodeMirror~'ext.CodeMirror.initialize'
|
||||||
|
* @fires CodeMirror~'ext.CodeMirror.ready'
|
||||||
* @stable to call and override
|
* @stable to call and override
|
||||||
*/
|
*/
|
||||||
initialize( extensions = this.defaultExtensions ) {
|
initialize( extensions = this.defaultExtensions ) {
|
||||||
|
@ -304,6 +305,49 @@ class CodeMirror {
|
||||||
// Also override textSelection() functions for the "real" hidden textarea to route to
|
// Also override textSelection() functions for the "real" hidden textarea to route to
|
||||||
// CodeMirror. We unregister this when switching to normal textarea mode.
|
// CodeMirror. We unregister this when switching to normal textarea mode.
|
||||||
this.$textarea.textSelection( 'register', this.cmTextSelection );
|
this.$textarea.textSelection( 'register', this.cmTextSelection );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called just after CodeMirror is initialized.
|
||||||
|
*
|
||||||
|
* @event CodeMirror~'ext.CodeMirror.ready'
|
||||||
|
* @param {jQuery} $view The CodeMirror view.
|
||||||
|
* @stable to use
|
||||||
|
*/
|
||||||
|
mw.hook( 'ext.CodeMirror.ready' ).fire( $( this.view.dom ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
const hasFocus = this.view.hasFocus;
|
||||||
|
const { from, to } = this.view.state.selection.ranges[ 0 ];
|
||||||
|
$( this.view.dom ).textSelection( 'unregister' );
|
||||||
|
this.$textarea.textSelection( 'unregister' );
|
||||||
|
this.$textarea.val( this.view.state.doc.toString() );
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -187,21 +187,7 @@ class CodeMirrorWikiEditor extends CodeMirror {
|
||||||
switchCodeMirror() {
|
switchCodeMirror() {
|
||||||
if ( this.view ) {
|
if ( this.view ) {
|
||||||
this.setCodeMirrorPreference( false );
|
this.setCodeMirrorPreference( false );
|
||||||
const scrollTop = this.view.scrollDOM.scrollTop;
|
this.destroy();
|
||||||
const hasFocus = this.view.hasFocus;
|
|
||||||
const { from, to } = this.view.state.selection.ranges[ 0 ];
|
|
||||||
$( this.view.dom ).textSelection( 'unregister' );
|
|
||||||
this.$textarea.textSelection( 'unregister' );
|
|
||||||
this.$textarea.val( this.view.state.doc.toString() );
|
|
||||||
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 );
|
|
||||||
mw.hook( 'ext.CodeMirror.switch' ).fire( false, this.$textarea );
|
mw.hook( 'ext.CodeMirror.switch' ).fire( false, this.$textarea );
|
||||||
} else {
|
} else {
|
||||||
this.enableCodeMirror();
|
this.enableCodeMirror();
|
||||||
|
|
Loading…
Reference in a new issue