diff --git a/bundlesize.config.json b/bundlesize.config.json index bef7f6d..74b488a 100644 --- a/bundlesize.config.json +++ b/bundlesize.config.json @@ -17,6 +17,6 @@ }, { "resourceModule": "skins.vector.legacy.js", - "maxSize": "1.7 kB" + "maxSize": "1.8 kB" } ] diff --git a/includes/Hooks.php b/includes/Hooks.php index f1c282d..5736335 100644 --- a/includes/Hooks.php +++ b/includes/Hooks.php @@ -2,11 +2,13 @@ namespace Vector; +use Config; use ExtensionRegistry; use HTMLForm; use MediaWiki\MediaWikiServices; use OutputPage; use RequestContext; +use ResourceLoaderContext; use Skin; use SkinTemplate; use SkinVector; @@ -19,6 +21,21 @@ use User; * on() */ class Hooks { + /** + * Passes config variables to Vector (modern) ResourceLoader module. + * @param ResourceLoaderContext $context + * @param Config $config + * @return array + */ + public static function getVectorResourceLoaderConfig( + ResourceLoaderContext $context, + Config $config + ) { + return [ + 'wgVectorUseCoreSearch' => $config->get( 'VectorUseCoreSearch' ), + ]; + } + /** * BeforePageDisplayMobile hook handler * @@ -52,6 +69,37 @@ class Hooks { } } + /** + * SkinPageReadyConfig hook handler + * + * Replace searchModule provided by skin. + * + * @since 1.35 + * @param ResourceLoaderContext $context + * @param mixed[] &$config Associative array of configurable options + * @return void This hook must not abort, it must return no value + */ + public static function onSkinPageReadyConfig( + ResourceLoaderContext $context, + array &$config + ) { + // It's better to exit before any additional check + if ( $context->getSkin() !== 'vector' ) { + return; + } + + // Tell the `mediawiki.page.ready` module not to wire up search. + // This allows us to use $wgVectorUseCoreSearch to decide to load + // the historic jquery autocomplete search or the new Vue implementation. + // ResourceLoaderContext has no knowledge of legacy / modern Vector + // and from its point of view they are the same thing. + // Please see the modules `skins.vector.js` and `skins.vector.legacy.js` + // for the wire up of search. + // The related method self::getVectorResourceLoaderConfig handles which + // search to load. + $config['search'] = false; + } + /** * Add icon class to an existing navigation item inside a menu hook. * See self::onSkinTemplateNavigation. diff --git a/jsdoc.json b/jsdoc.json index e7f4ab4..c65ce84 100644 --- a/jsdoc.json +++ b/jsdoc.json @@ -25,8 +25,9 @@ "CheckboxHack": "https://doc.wikimedia.org/mediawiki-core/master/js", "MW": "https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw", + "MediaWikiPageReadyModule": "https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.plugin.page.ready", "JQueryStatic": "https://api.jquery.com", - + "VectorResourceLoaderVirtualConfig": "#", "void": "#" } } diff --git a/resources/MediaWikiPageReady.d.ts b/resources/MediaWikiPageReady.d.ts new file mode 100644 index 0000000..95fb117 --- /dev/null +++ b/resources/MediaWikiPageReady.d.ts @@ -0,0 +1,7 @@ +interface MediaWikiPageReadyModule { + /** + * Loads search module when search input is focused. + * @param {string} moduleName to load on input focus. + */ + loadSearchModule(moduleName: string): void +} diff --git a/resources/VectorResourceLoaderVirtualConfig.d.ts b/resources/VectorResourceLoaderVirtualConfig.d.ts new file mode 100644 index 0000000..a460c4d --- /dev/null +++ b/resources/VectorResourceLoaderVirtualConfig.d.ts @@ -0,0 +1,7 @@ +/** See Vector\Hooks::getVectorResourceLoaderConfig */ +interface VectorResourceLoaderVirtualConfig { + /** + * The name of the ResourceLoader module that contains search. + */ + wgVectorUseCoreSearch: boolean +} diff --git a/resources/skins.vector.js/skin.js b/resources/skins.vector.js/skin.js index f478385..471ff1c 100644 --- a/resources/skins.vector.js/skin.js +++ b/resources/skins.vector.js/skin.js @@ -1,5 +1,12 @@ +/** @interface VectorResourceLoaderVirtualConfig */ +/** @interface MediaWikiPageReadyModule */ + var collapsibleTabs = require( '../skins.vector.legacy.js/collapsibleTabs.js' ), vector = require( '../skins.vector.legacy.js/vector.js' ), + /** @type {VectorResourceLoaderVirtualConfig} */ + config = require( /** @type {string} */ ( './config.json' ) ), + /** @type {MediaWikiPageReadyModule} */ + pageReady = require( /** @type {string} */( 'mediawiki.page.ready' ) ), sidebar = require( './sidebar.js' ); /** @@ -43,6 +50,11 @@ function main( window ) { collapsibleTabs.init(); sidebar.init( window ); $( vector.init ); + pageReady.loadSearchModule( + // Decide between new Vue implementation or old. + config.wgVectorUseCoreSearch ? + 'mediawiki.searchSuggest' : 'skins.vector.search' + ); } main( window ); diff --git a/resources/skins.vector.legacy.js/skin-legacy.js b/resources/skins.vector.legacy.js/skin-legacy.js index 40eff8a..8907e02 100644 --- a/resources/skins.vector.legacy.js/skin-legacy.js +++ b/resources/skins.vector.legacy.js/skin-legacy.js @@ -1,10 +1,14 @@ +/** @interface MediaWikiPageReadyModule */ var collapsibleTabs = require( './collapsibleTabs.js' ), + /** @type {MediaWikiPageReadyModule} */ + pageReady = require( /** @type {string} */( 'mediawiki.page.ready' ) ), vector = require( './vector.js' ); function main() { collapsibleTabs.init(); $( vector.init ); + pageReady.loadSearchModule( 'mediawiki.searchSuggest' ); } main(); diff --git a/skin.json b/skin.json index ee18dba..e292653 100644 --- a/skin.json +++ b/skin.json @@ -49,6 +49,7 @@ }, "Hooks": { "BeforePageDisplay": "Vector\\Hooks::onBeforePageDisplay", + "SkinPageReadyConfig": "Vector\\Hooks::onSkinPageReadyConfig", "GetPreferences": "Vector\\Hooks::onGetPreferences", "PreferencesFormPreSave": "Vector\\Hooks::onPreferencesFormPreSave", "SkinTemplateNavigation": "Vector\\Hooks::onSkinTemplateNavigation", @@ -96,16 +97,25 @@ ], "styles": [ "resources/skins.vector.styles.responsive.less" ] }, + "skins.vector.search": { + "dependencies": [ + "vue" + ] + }, "skins.vector.js": { "packageFiles": [ "resources/skins.vector.js/skin.js", + { + "name": "resources/skins.vector.js/config.json", + "callback": "Vector\\Hooks::getVectorResourceLoaderConfig" + }, "resources/skins.vector.js/sidebar.js", "resources/skins.vector.legacy.js/collapsibleTabs.js", "resources/skins.vector.legacy.js/vector.js" ], "dependencies": [ - "mediawiki.util", - "mediawiki.page.ready" + "mediawiki.page.ready", + "mediawiki.util" ] }, "skins.vector.legacy.js": { @@ -115,6 +125,7 @@ "resources/skins.vector.legacy.js/vector.js" ], "dependencies": [ + "mediawiki.page.ready", "mediawiki.util" ] } @@ -172,6 +183,9 @@ "value": "1", "description": "@var string:['2'|'1'] The version ('2' for latest, '1' for legacy) of the Vector skin to **set** for newly created user accounts. **The value is persisted as a user preference.** This configuration is not used for preexisting accounts (see VectorDefaultSkinVersionForExistingAccounts) and only ever executed once at new account creation time." }, + "VectorUseCoreSearch": { + "value": true + }, "VectorDefaultSidebarVisibleForAuthorisedUser": { "value": true },