diff --git a/bundlesize.config.json b/bundlesize.config.json
index 7cb0bd8b9..0c0ecb9d6 100644
--- a/bundlesize.config.json
+++ b/bundlesize.config.json
@@ -18,15 +18,7 @@
},
{
"resourceModule": "mmv.bootstrap",
- "maxSize": "5.9 kB"
- },
- {
- "resourceModule": "mmv.bootstrap.autostart",
- "maxSize": "1 kB"
- },
- {
- "resourceModule": "mmv.head",
- "maxSize": "1 kB"
+ "maxSize": "5.6 kB"
}
]
}
diff --git a/extension.json b/extension.json
index fa651ae30..5448c682a 100644
--- a/extension.json
+++ b/extension.json
@@ -97,8 +97,7 @@
"mediawiki.user",
"mediawiki.util",
"mmv.bootstrap",
- "mmv.codex",
- "mmv.head"
+ "mmv.codex"
],
"messages": [
"license-header",
@@ -279,6 +278,7 @@
"extensions": "MediaViewerExtensions"
}
},
+ "mmv.bootstrap/mmv.bootstrap.autostart.js",
"mmv.bootstrap/mmv.bootstrap.js",
"mmv.bootstrap/mmv.lightboximage.js",
"mmv.bootstrap/mmv.Config.js",
@@ -293,8 +293,7 @@
"mediawiki.router",
"mediawiki.Title",
"mediawiki.user",
- "mediawiki.storage",
- "mmv.head"
+ "mediawiki.storage"
],
"messages": [
"multimediaviewer-loading",
@@ -305,23 +304,12 @@
]
},
"mmv.bootstrap.autostart": {
- "packageFiles": [
- "mmv.bootstrap.autostart/mmv.bootstrap.autostart.js"
- ],
- "dependencies": [
- "mmv.head",
- "mmv.bootstrap"
- ]
+ "deprecated": "Deprecated in 1.43, alias for mmw.bootstrap",
+ "dependencies": "mmv.bootstrap"
},
"mmv.head": {
- "packageFiles": [
- "mmv.head/mmv.head.js",
- "mmv.head/base.js"
- ],
- "dependencies": [
- "mediawiki.user",
- "mediawiki.storage"
- ]
+ "deprecated": "Deprecated in 1.43, alias for mmw.bootstrap",
+ "dependencies": "mmv.bootstrap"
}
},
"ResourceFileModulePaths": {
@@ -369,7 +357,6 @@
"tests/qunit/mmv/mmv.testhelpers.js"
],
"dependencies": [
- "mmv.head",
"mmv.bootstrap",
"mmv",
"mmv.ui.reuse"
diff --git a/includes/Hooks.php b/includes/Hooks.php
index b5725814d..5bab83584 100644
--- a/includes/Hooks.php
+++ b/includes/Hooks.php
@@ -111,7 +111,7 @@ class Hooks implements
$isMobileFrontendView = ExtensionRegistry::getInstance()->isLoaded( 'MobileFrontend' ) &&
$this->mobileContext && $this->mobileContext->shouldDisplayMobileView();
if ( !$isMobileFrontendView ) {
- $out->addModules( [ 'mmv.head', 'mmv.bootstrap.autostart' ] );
+ $out->addModules( [ 'mmv.bootstrap' ] );
}
}
diff --git a/resources/mmv.bootstrap/mmv.Config.js b/resources/mmv.bootstrap/mmv.Config.js
index 53790709d..cebfd40fe 100644
--- a/resources/mmv.bootstrap/mmv.Config.js
+++ b/resources/mmv.bootstrap/mmv.Config.js
@@ -15,13 +15,74 @@
* along with MediaViewer. If not, see .
*/
-const { isMediaViewerEnabledOnClick } = require( 'mmv.head' );
const api = new mw.Api();
/**
* Contains/retrieves configuration/environment information for MediaViewer.
*/
class Config {
+
+ /**
+ * The media route prefix
+ *
+ * @return {string}
+ */
+ static get ROUTE() {
+ return 'media';
+ }
+
+ /**
+ * RegExp representing the media route
+ *
+ * @return {RegExp}
+ */
+ static get ROUTE_REGEXP() {
+ return /^\/media\/(.+)$/;
+ }
+
+ /**
+ * RegExp representing the media position as in "File:foo.jpg/3"
+ *
+ * @return {RegExp}
+ */
+ static get POSITION_REGEXP() {
+ return /\/(\d+)$/;
+ }
+
+ /**
+ * Regular expression representing the legacy media route
+ *
+ * @return {RegExp}
+ */
+ static get LEGACY_ROUTE_REGEXP() {
+ return /^mediaviewer\/(.+)$/;
+ }
+
+ /**
+ * Returns true if MediaViewer should handle thumbnail clicks.
+ *
+ * @return {boolean}
+ */
+ static isMediaViewerEnabledOnClick() {
+ return mw.config.get( 'wgMediaViewer' ) && // global opt-out switch, can be set in user JS
+ mw.config.get( 'wgMediaViewerOnClick' ) && // thumbnail opt-out, can be set in preferences
+ ( mw.user.isNamed() || !mw.storage.get( 'wgMediaViewerOnClick' ) || mw.storage.get( 'wgMediaViewerOnClick' ) === '1' ); // thumbnail opt-out for anons
+ }
+
+ /**
+ * Returns the location hash (route string) for the given file title.
+ *
+ * @param {string} imageFileTitle the file title
+ * @param {number} [position] the relative position of this image to others with same file
+ * @return {string} the location hash
+ * @member mw.mmv
+ */
+ static getMediaHash( imageFileTitle, position ) {
+ return position > 1 ?
+ `#/${ this.ROUTE }/${ encodeURI( imageFileTitle ) }/${ position }` :
+ `#/${ this.ROUTE }/${ encodeURI( imageFileTitle ) }`;
+ }
+
/**
* (Semi-)permanently stores the setting whether MediaViewer should handle thumbnail clicks.
* - for logged-in users, we use preferences
@@ -79,7 +140,7 @@ class Config {
* @return {boolean}
*/
static shouldShowStatusInfo() {
- return !isMediaViewerEnabledOnClick( mw.config, mw.user, mw.storage ) && mw.storage.get( 'mmv-showStatusInfo' ) === '1';
+ return !this.isMediaViewerEnabledOnClick() && mw.storage.get( 'mmv-showStatusInfo' ) === '1';
}
/**
@@ -112,4 +173,5 @@ class Config {
}
}
+mw.mmv = Config;
module.exports = Config;
diff --git a/resources/mmv.bootstrap.autostart/mmv.bootstrap.autostart.js b/resources/mmv.bootstrap/mmv.bootstrap.autostart.js
similarity index 75%
rename from resources/mmv.bootstrap.autostart/mmv.bootstrap.autostart.js
rename to resources/mmv.bootstrap/mmv.bootstrap.autostart.js
index 3d3f25cbc..8806b73cc 100644
--- a/resources/mmv.bootstrap.autostart/mmv.bootstrap.autostart.js
+++ b/resources/mmv.bootstrap/mmv.bootstrap.autostart.js
@@ -18,10 +18,13 @@
// This file is used to do the global initialization that we want on the real pages,
// but do not want in the tests.
-const { MultimediaViewerBootstrap } = require( 'mmv.bootstrap' );
+const Config = require( './mmv.Config.js' );
+const MultimediaViewerBootstrap = require( './mmv.bootstrap.js' );
+const LightboxImage = require( './mmv.lightboximage.js' );
+const HtmlUtils = require( './mmv.HtmlUtils.js' );
const bootstrap = new MultimediaViewerBootstrap();
$( bootstrap.setupEventHandlers.bind( bootstrap ) );
-module.exports = bootstrap;
+module.exports = { MultimediaViewerBootstrap, LightboxImage, Config, HtmlUtils };
diff --git a/resources/mmv.bootstrap/mmv.bootstrap.js b/resources/mmv.bootstrap/mmv.bootstrap.js
index c498dd474..d247da603 100644
--- a/resources/mmv.bootstrap/mmv.bootstrap.js
+++ b/resources/mmv.bootstrap/mmv.bootstrap.js
@@ -15,7 +15,6 @@
* along with MultimediaViewer. If not, see .
*/
-const { getMediaHash, ROUTE_REGEXP, POSITION_REGEXP, LEGACY_ROUTE_REGEXP, isMediaViewerEnabledOnClick } = require( 'mmv.head' );
const Config = require( './mmv.Config.js' );
const HtmlUtils = require( './mmv.HtmlUtils.js' );
const LightboxImage = require( './mmv.lightboximage.js' );
@@ -70,10 +69,10 @@ class MultimediaViewerBootstrap {
let fileTitle;
viewer.comingFromHashChange = true;
try {
- let position = fileName.match( POSITION_REGEXP );
+ let position = fileName.match( Config.POSITION_REGEXP );
if ( position ) {
position = +position[ 1 ];
- fileName = fileName.replace( POSITION_REGEXP, '' );
+ fileName = fileName.replace( Config.POSITION_REGEXP, '' );
} else {
position = undefined;
}
@@ -93,8 +92,8 @@ class MultimediaViewerBootstrap {
* @param {OO.Router} router
*/
setupRouter( router ) {
- router.addRoute( ROUTE_REGEXP, this.route.bind( this ) );
- router.addRoute( LEGACY_ROUTE_REGEXP, this.route.bind( this ) );
+ router.addRoute( Config.ROUTE_REGEXP, this.route.bind( this ) );
+ router.addRoute( Config.LEGACY_ROUTE_REGEXP, this.route.bind( this ) );
this.router = router;
}
@@ -206,9 +205,6 @@ class MultimediaViewerBootstrap {
this.$parsoidThumbs.each( ( i, thumb ) => this.processParsoidThumb( thumb ) );
} finally {
this.thumbsReadyDeferred.resolve();
- // now that we have set up our real click handler we can remove the temporary
- // handler added in mmv.head.js which just replays clicks to the real handler
- $( document ).off( 'click.mmv-head' );
}
}
@@ -248,7 +244,7 @@ class MultimediaViewerBootstrap {
$thumbContainer.on( {
mouseenter: () => {
// There is no point preloading if clicking the thumb won't open Media Viewer
- if ( !isMediaViewerEnabledOnClick() ) {
+ if ( !Config.isMediaViewerEnabledOnClick() ) {
return;
}
this.preloadOnHoverTimer = setTimeout( () => {
@@ -507,7 +503,7 @@ class MultimediaViewerBootstrap {
*/
openImage( image ) {
this.ensureEventHandlersAreSetUp();
- const hash = getMediaHash( image.filePageTitle, image.position );
+ const hash = Config.getMediaHash( image.filePageTitle, image.position );
location.hash = hash;
history.replaceState( MANAGED_STATE, null, hash );
}
@@ -527,7 +523,7 @@ class MultimediaViewerBootstrap {
}
// Don't load if someone has specifically stopped us from doing so
- if ( !isMediaViewerEnabledOnClick() ) {
+ if ( !Config.isMediaViewerEnabledOnClick() ) {
return true;
}
@@ -553,7 +549,7 @@ class MultimediaViewerBootstrap {
*/
isViewerHash() {
const path = location.hash.slice( 1 );
- return path.match( ROUTE_REGEXP ) || path.match( LEGACY_ROUTE_REGEXP );
+ return path.match( Config.ROUTE_REGEXP ) || path.match( Config.LEGACY_ROUTE_REGEXP );
}
/**
@@ -685,4 +681,4 @@ class MultimediaViewerBootstrap {
}
}
-module.exports = { MultimediaViewerBootstrap, LightboxImage, Config, HtmlUtils };
+module.exports = MultimediaViewerBootstrap;
diff --git a/resources/mmv.head/base.js b/resources/mmv.head/base.js
deleted file mode 100644
index c6169fff8..000000000
--- a/resources/mmv.head/base.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * This file is part of the MediaWiki extension MultimediaViewer.
- *
- * MultimediaViewer is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * MultimediaViewer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with MultimediaViewer. If not, see .
- */
-
-// Included on every page which has images so keep it lightweight.
-module.exports = {
- /**
- * The media route prefix
- *
- * @member mw.mmv
- */
- ROUTE: 'media',
- /**
- * RegExp representing the media route
- *
- * @member mw.mmv
- */
- ROUTE_REGEXP: /^\/media\/(.+)$/,
- /**
- * RegExp representing the media position as in "File:foo.jpg/3"
- *
- * @member mw.mmv
- */
- POSITION_REGEXP: /\/(\d+)$/,
- /**
- * @property {RegExp}
- * Regular expression representing the legacy media route
- * @member mw.mmv
- */
- LEGACY_ROUTE_REGEXP: /^mediaviewer\/(.+)$/,
-
- /**
- * Returns true if MediaViewer should handle thumbnail clicks.
- *
- * @param {Map} mwConfig
- * @param {Object} mwUser
- * @param {mw.SafeStorage} mwStorage
- * @return {boolean}
- */
- isMediaViewerEnabledOnClick( mwConfig = mw.config, mwUser = mw.user, mwStorage = mw.storage ) {
- return mwConfig.get( 'wgMediaViewer' ) && // global opt-out switch, can be set in user JS
- mwConfig.get( 'wgMediaViewerOnClick' ) && // thumbnail opt-out, can be set in preferences
- ( mwUser.isNamed() || !mwStorage.get( 'wgMediaViewerOnClick' ) || mwStorage.get( 'wgMediaViewerOnClick' ) === '1' ); // thumbnail opt-out for anons
- },
-
- /**
- * Returns the location hash (route string) for the given file title.
- *
- * @param {string} imageFileTitle the file title
- * @param {number} [position] the relative position of this image to others with same file
- * @return {string} the location hash
- * @member mw.mmv
- */
- getMediaHash: ( imageFileTitle, position ) => position > 1 ?
- `#/media/${ encodeURI( imageFileTitle ) }/${ position }` :
- `#/media/${ encodeURI( imageFileTitle ) }`
-};
diff --git a/resources/mmv.head/mmv.head.js b/resources/mmv.head/mmv.head.js
deleted file mode 100644
index 72131e904..000000000
--- a/resources/mmv.head/mmv.head.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * This file is part of the MediaWiki extension MultimediaViewer.
- *
- * MultimediaViewer is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * MultimediaViewer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with MultimediaViewer. If not, see .
- */
-
-const base = require( './base.js' );
-mw.mmv = base;
-module.exports = base;
-
-// If MediaViewer is disabled by the user, do not set up click handling.
-// This is loaded before user JS so we cannot check wgMediaViewer.
-if ( base.isMediaViewerEnabledOnClick() ) {
- ( $( document ) ).on( 'click.mmv-head', 'a.image, a.mw-file-description', ( e ) => {
- // Do not interfere with non-left clicks or if modifier keys are pressed.
- // Also, make sure we do not get in a loop.
- if ( ( e.button !== 0 && e.which !== 1 ) || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey || e.replayed ) {
- return;
- }
-
- // We wait for document readiness because mw.loader.using writes to the DOM
- // which can cause a blank page if it happens before DOM readiness
- $( () => {
- mw.loader.using( [ 'mmv.bootstrap.autostart' ], ( req ) => {
- const bootstrap = req( 'mmv.bootstrap.autostart' );
- bootstrap.whenThumbsReady().then( () => {
- // We have to copy the properties, passing e doesn't work. Probably because of preventDefault()
- $( e.target ).trigger( { type: 'click', which: 1, replayed: true } );
- } );
- } );
- } );
-
- e.preventDefault();
- } );
-}
diff --git a/resources/mmv.ui.reuse/mmv.EmbedFileFormatter.js b/resources/mmv.ui.reuse/mmv.EmbedFileFormatter.js
index 75138a444..30825740b 100644
--- a/resources/mmv.ui.reuse/mmv.EmbedFileFormatter.js
+++ b/resources/mmv.ui.reuse/mmv.EmbedFileFormatter.js
@@ -15,8 +15,7 @@
* along with MediaViewer. If not, see .
*/
-const { getMediaHash } = require( 'mmv.head' );
-const { HtmlUtils } = require( 'mmv.bootstrap' );
+const { Config, HtmlUtils } = require( 'mmv.bootstrap' );
/**
* Converts data in various formats needed by the Embed sub-dialog
@@ -173,7 +172,7 @@ class EmbedFileFormatter {
return HtmlUtils.jqueryToHtml(
$( '
' ).append(
$( '' )
- .attr( 'href', info.imageInfo.descriptionUrl + getMediaHash( info.imageInfo.title ) )
+ .attr( 'href', info.imageInfo.descriptionUrl + Config.getMediaHash( info.imageInfo.title ) )
.append(
$( '' )
.attr( 'src', imgUrl )
diff --git a/resources/mmv.ui.reuse/mmv.ui.reuse.share.js b/resources/mmv.ui.reuse/mmv.ui.reuse.share.js
index cf913b47d..3555471c6 100644
--- a/resources/mmv.ui.reuse/mmv.ui.reuse.share.js
+++ b/resources/mmv.ui.reuse/mmv.ui.reuse.share.js
@@ -15,7 +15,7 @@
* along with MultimediaViewer. If not, see .
*/
-const { getMediaHash } = require( 'mmv.head' );
+const { Config } = require( 'mmv.bootstrap' );
const Utils = require( './mmv.ui.utils.js' );
const { UiElement } = require( 'mmv' );
@@ -56,7 +56,7 @@ class Share extends UiElement {
* @param {ImageModel} image
*/
set( image ) {
- const url = image.descriptionUrl + getMediaHash( image.title );
+ const url = image.descriptionUrl + Config.getMediaHash( image.title );
this.$pageInput.val( url );
}
diff --git a/resources/mmv/mmv.js b/resources/mmv/mmv.js
index 21a2cf889..620d3bfda 100644
--- a/resources/mmv/mmv.js
+++ b/resources/mmv/mmv.js
@@ -16,7 +16,6 @@
*/
const { Config } = require( 'mmv.bootstrap' );
-const { getMediaHash } = require( 'mmv.head' );
const ViewLogger = require( './logging/mmv.logging.ViewLogger.js' );
const Api = require( './provider/mmv.provider.Api.js' );
const GuessedThumbnailInfo = require( './provider/mmv.provider.GuessedThumbnailInfo.js' );
@@ -639,7 +638,7 @@ class MultimediaViewer {
const thumb = this.thumbs[ index ];
this.loadImage( thumb );
router.navigateTo( null, {
- path: getMediaHash( thumb.filePageTitle, thumb.position ),
+ path: Config.getMediaHash( thumb.filePageTitle, thumb.position ),
useReplaceState: true
} );
}
diff --git a/tests/qunit/mmv/mmv.Config.test.js b/tests/qunit/mmv/mmv.Config.test.js
index b1a723b3a..cb6bc0b53 100644
--- a/tests/qunit/mmv/mmv.Config.test.js
+++ b/tests/qunit/mmv/mmv.Config.test.js
@@ -15,7 +15,6 @@
* along with MediaViewer. If not, see .
*/
-const { isMediaViewerEnabledOnClick } = require( 'mmv.head' );
const { Config } = require( 'mmv.bootstrap' );
const { createLocalStorage, getFakeLocalStorage } = require( './mmv.testhelpers.js' );
const config0 = mw.config;
@@ -46,39 +45,39 @@ const saveOption = mw.Api.prototype.saveOption;
mw.user.isNamed.returns( true );
mw.config.get.withArgs( 'wgMediaViewer' ).returns( true );
mw.config.get.withArgs( 'wgMediaViewerOnClick' ).returns( true );
- assert.strictEqual( isMediaViewerEnabledOnClick( mw.config, mw.user ), true, 'Returns true for logged-in with standard settings' );
+ assert.strictEqual( Config.isMediaViewerEnabledOnClick(), true, 'Returns true for logged-in with standard settings' );
mw.user.isNamed.returns( true );
mw.config.get.withArgs( 'wgMediaViewer' ).returns( false );
mw.config.get.withArgs( 'wgMediaViewerOnClick' ).returns( true );
- assert.strictEqual( isMediaViewerEnabledOnClick( mw.config, mw.user ), false, 'Returns false if opted out via user JS flag' );
+ assert.strictEqual( Config.isMediaViewerEnabledOnClick(), false, 'Returns false if opted out via user JS flag' );
mw.user.isNamed.returns( true );
mw.config.get.withArgs( 'wgMediaViewer' ).returns( true );
mw.config.get.withArgs( 'wgMediaViewerOnClick' ).returns( false );
- assert.strictEqual( isMediaViewerEnabledOnClick( mw.config, mw.user ), false, 'Returns false if opted out via preferences' );
+ assert.strictEqual( Config.isMediaViewerEnabledOnClick(), false, 'Returns false if opted out via preferences' );
mw.user.isNamed.returns( false );
mw.config.get.withArgs( 'wgMediaViewer' ).returns( false );
mw.config.get.withArgs( 'wgMediaViewerOnClick' ).returns( true );
- assert.strictEqual( isMediaViewerEnabledOnClick( mw.config, mw.user ), false, 'Returns false if anon user opted out via user JS flag' );
+ assert.strictEqual( Config.isMediaViewerEnabledOnClick(), false, 'Returns false if anon user opted out via user JS flag' );
mw.user.isNamed.returns( false );
mw.config.get.withArgs( 'wgMediaViewer' ).returns( true );
mw.config.get.withArgs( 'wgMediaViewerOnClick' ).returns( false );
- assert.strictEqual( isMediaViewerEnabledOnClick( mw.config, mw.user ), false, 'Returns false if anon user opted out in some weird way' ); // apparently someone created a browser extension to do this
+ assert.strictEqual( Config.isMediaViewerEnabledOnClick(), false, 'Returns false if anon user opted out in some weird way' ); // apparently someone created a browser extension to do this
mw.user.isNamed.returns( false );
mw.config.get.withArgs( 'wgMediaViewer' ).returns( true );
mw.config.get.withArgs( 'wgMediaViewerOnClick' ).returns( true );
mw.storage.store.getItem.withArgs( 'wgMediaViewerOnClick' ).returns( null );
- assert.strictEqual( isMediaViewerEnabledOnClick( mw.config, mw.user ), true, 'Returns true for anon with standard settings' );
+ assert.strictEqual( Config.isMediaViewerEnabledOnClick(), true, 'Returns true for anon with standard settings' );
mw.user.isNamed.returns( false );
mw.config.get.withArgs( 'wgMediaViewer' ).returns( true );
mw.config.get.withArgs( 'wgMediaViewerOnClick' ).returns( true );
mw.storage.store.getItem.withArgs( 'wgMediaViewerOnClick' ).returns( '0' );
- assert.strictEqual( isMediaViewerEnabledOnClick( mw.config, mw.user ), false, 'Returns true for anon opted out via localSettings' );
+ assert.strictEqual( Config.isMediaViewerEnabledOnClick(), false, 'Returns true for anon opted out via localSettings' );
} );
QUnit.test( 'setMediaViewerEnabledOnClick sense check', function ( assert ) {