From c853e9587d28b401112e83b97355f5269734a559 Mon Sep 17 00:00:00 2001 From: MusikAnimal Date: Mon, 15 Apr 2024 01:05:07 -0400 Subject: [PATCH] CM6: Rework ResourceLoader modules Documentation is at https://w.wiki/9kxt The idea is that modules ending in `.init` imply they initialize CodeMirror and maniuplate the DOM. The others only export classes for use in integreations. In doing so, 'ext.CodeMirror.v6.WikiEditor' now only exports the CodeMirrorWikiEditor class, while 'ext.CodeMirror.v6.WikiEditor.init' is added for use on #wpTextbox1 through action=edit. Bug: T174811 Change-Id: Iec62ac9dc77918904bed886d2d46ccc03e0927f7 --- extension.json | 16 ++++++++++++---- includes/Hooks.php | 4 ++-- resources/dist/codemirror.wikieditor.js | 1 + .../dist/codemirror.wikieditor.mediawiki.js | 2 +- rollup.config.js | 2 ++ tests/phpunit/HookTest.php | 4 ++-- 6 files changed, 20 insertions(+), 9 deletions(-) create mode 100644 resources/dist/codemirror.wikieditor.js diff --git a/extension.json b/extension.json index 86ecdde1..364024bd 100644 --- a/extension.json +++ b/extension.json @@ -259,14 +259,22 @@ "ext.CodeMirror.v6.WikiEditor": { "dependencies": [ "ext.wikiEditor", - "ext.CodeMirror.v6.lib", + "ext.CodeMirror.v6" + ], + "packageFiles": [ + "dist/codemirror.wikieditor.js" + ], + "messages": [ + "codemirror-toggle-label" + ] + }, + "ext.CodeMirror.v6.WikiEditor.init": { + "dependencies": [ + "ext.CodeMirror.v6.WikiEditor", "ext.CodeMirror.v6.mode.mediawiki" ], "packageFiles": [ "dist/codemirror.wikieditor.mediawiki.js" - ], - "messages": [ - "codemirror-toggle-label" ] } }, diff --git a/includes/Hooks.php b/includes/Hooks.php index ab748169..b9ad784f 100644 --- a/includes/Hooks.php +++ b/includes/Hooks.php @@ -125,7 +125,7 @@ class Hooks implements if ( $this->shouldUseV6( $out ) ) { $out->addModules( $useWikiEditor ? - 'ext.CodeMirror.v6.WikiEditor' : + 'ext.CodeMirror.v6.WikiEditor.init' : 'ext.CodeMirror.v6.init' ); } else { @@ -149,7 +149,7 @@ class Hooks implements if ( $this->shouldUseV6( $out ) && $this->shouldLoadCodeMirror( $out ) ) { $useWikiEditor = $this->userOptionsLookup->getBoolOption( $out->getUser(), 'usebetatoolbar' ); $out->addModules( $useWikiEditor ? - 'ext.CodeMirror.v6.WikiEditor' : + 'ext.CodeMirror.v6.WikiEditor.init' : 'ext.CodeMirror.v6.init' ); } diff --git a/resources/dist/codemirror.wikieditor.js b/resources/dist/codemirror.wikieditor.js new file mode 100644 index 00000000..06314f14 --- /dev/null +++ b/resources/dist/codemirror.wikieditor.js @@ -0,0 +1 @@ +"use strict";var e=require("ext.CodeMirror.v6.lib"),t=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.realtimePreviewHandler=null,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.updateListener.of((function(e){e.docChanged&&"function"==typeof t.realtimePreviewHandler&&t.realtimePreviewHandler()}))];if(this.initialize(s),this.addRealtimePreviewHandler(),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})}a&&this.view.focus(),mw.hook("ext.CodeMirror.switch").fire(!0,$(this.view.dom))}}},{key:"addRealtimePreviewHandler",value:function(){var e=this;mw.hook("ext.WikiEditor.realtimepreview.enable").add((function(t){e.realtimePreviewHandler=t.getEventHandler().bind(t)})),mw.hook("ext.WikiEditor.realtimepreview.disable").add((function(){e.realtimePreviewHandler=null}))}},{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}(require("ext.CodeMirror.v6"));module.exports=t; diff --git a/resources/dist/codemirror.wikieditor.mediawiki.js b/resources/dist/codemirror.wikieditor.mediawiki.js index 922ea696..86cc50fd 100644 --- a/resources/dist/codemirror.wikieditor.mediawiki.js +++ b/resources/dist/codemirror.wikieditor.mediawiki.js @@ -1 +1 @@ -"use strict";var e=require("ext.CodeMirror.v6.lib"),t=require("ext.CodeMirror.v6"),i=require("ext.CodeMirror.v6.mode.mediawiki"),r=function(t){function i(t,r){var o;return e._classCallCheck(this,i),(o=e._callSuper(this,i,[t])).langExtension=r,o.useCodeMirror=mw.user.options.get("usecodemirror")>0,o.realtimePreviewHandler=null,o}return e._inherits(i,t),e._createClass(i,[{key:"setCodeMirrorPreference",value:function(t){this.useCodeMirror=t,e._get(e._getPrototypeOf(i.prototype),"setCodeMirrorPreference",this).call(this,t)}},{key:"enableCodeMirror",value:function(){var t=this;if(!this.view){var i=this.$textarea.prop("selectionStart"),r=this.$textarea.prop("selectionEnd"),o=this.$textarea.scrollTop(),a=this.$textarea.is(":focus"),s=[this.defaultExtensions,this.langExtension,e.EditorView.updateListener.of((function(e){e.docChanged&&"function"==typeof t.realtimePreviewHandler&&t.realtimePreviewHandler()}))];if(this.initialize(s),this.addRealtimePreviewHandler(),requestAnimationFrame((function(){t.view.scrollDOM.scrollTop=o})),0!==i||0!==r){var d=e.EditorSelection.range(i,r),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:"addRealtimePreviewHandler",value:function(){var e=this;mw.hook("ext.WikiEditor.realtimepreview.enable").add((function(t){e.realtimePreviewHandler=t.getEventHandler().bind(t)})),mw.hook("ext.WikiEditor.realtimepreview.disable").add((function(){e.realtimePreviewHandler=null}))}},{key:"addCodeMirrorToWikiEditor",value:function(){var e=this,t=this.$textarea.data("wikiEditor-context"),i=t&&t.modules&&t.modules.toolbar;i&&(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()}}}}}}}),i.$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})}}]),i}(t),o=new URLSearchParams(window.location.search);mw.loader.getState("ext.wikiEditor")&&mw.hook("wikiEditor.toolbarReady").add((function(e){new r(e,i({bidiIsolation:"rtl"===e.attr("dir")&&o.get("cm6bidi")})).addCodeMirrorToWikiEditor()})); +"use strict";var r=require("ext.CodeMirror.v6.WikiEditor"),i=require("ext.CodeMirror.v6.mode.mediawiki");require("ext.CodeMirror.v6.lib"),require("ext.CodeMirror.v6");var e=new URLSearchParams(window.location.search);mw.loader.getState("ext.wikiEditor")&&mw.hook("wikiEditor.toolbarReady").add((function(o){new r(o,i({bidiIsolation:"rtl"===o.attr("dir")&&e.get("cm6bidi")})).addCodeMirrorToWikiEditor()})); diff --git a/rollup.config.js b/rollup.config.js index 4da6b50d..0f1cf326 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -13,6 +13,7 @@ const terser = require( '@rollup/plugin-terser' ); const importAliases = { './vendor.js': 'ext.CodeMirror.v6.lib', './codemirror.js': 'ext.CodeMirror.v6', + './codemirror.wikieditor.js': 'ext.CodeMirror.v6.WikiEditor', './codemirror.mode.mediawiki.js': 'ext.CodeMirror.v6.mode.mediawiki' }; @@ -23,6 +24,7 @@ module.exports = [ 'src/codemirror.js', 'src/codemirror.mode.mediawiki.js', 'src/codemirror.mediawiki.js', + 'src/codemirror.wikieditor.js', 'src/codemirror.wikieditor.mediawiki.js' ], diff --git a/tests/phpunit/HookTest.php b/tests/phpunit/HookTest.php index b7f1dec5..e44f9338 100644 --- a/tests/phpunit/HookTest.php +++ b/tests/phpunit/HookTest.php @@ -70,9 +70,9 @@ class HookTest extends MediaWikiIntegrationTestCase { public static function provideOnEditPageShowEditFormInitial(): Generator { // useCodeMirrorV6, expectedAddModuleCalls, expectedFirstModule, readOnly yield 'CM5' => [ false, 2, 'ext.CodeMirror.WikiEditor' ]; - yield 'CM6' => [ true, 1, 'ext.CodeMirror.v6.WikiEditor' ]; + yield 'CM6' => [ true, 1, 'ext.CodeMirror.v6.WikiEditor.init' ]; yield 'CM5 read-only' => [ false, 0, null, true ]; - yield 'CM6 read-only' => [ true, 1, 'ext.CodeMirror.v6.WikiEditor', true ]; + yield 'CM6 read-only' => [ true, 1, 'ext.CodeMirror.v6.WikiEditor.init', true ]; } /**