mediawiki-extensions-Visual.../modules/ve-mw/preinit/ve.init.mw.DiffPage.init.js
jwbth 6d7a062dbb Fix history.replaceState call on diff pages
The history.replaceState call in onReviewModeButtonSelectSelect() (1)
ignores any changes to the document URL made by external tools such as
RevisionSlider, (2) replaces with an empty string the history entry
state object if it was set by external tools such as, again,
RevisionSlider. Both 1 and 2 result in a wrong URL ending up in the
address bar at some point. This patch addresses these problems, (1)
creating a new mw.Uri() object every time
onReviewModeButtonSelectSelect() is called, (2) keeping the current
history.state object.

The original variable storing the URI object is renamed to avoid
shadowing (optionally can be replaced with its value as it's used only
once).

Bug: T288636
Change-Id: Ieb97b561a6c076aa28aae231fe286ac4d1051bbd
2021-08-14 10:51:24 +00:00

121 lines
4.9 KiB
JavaScript

/*!
* VisualEditor MediaWiki DiffPage init.
*
* @copyright 2011-2020 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/* eslint-disable no-jquery/no-global-selector */
( function () {
var reviewModeButtonSelect, lastDiff,
$wikitextDiffContainer, $wikitextDiffHeader, $wikitextDiffBody,
$visualDiffContainer = $( '<div>' ),
$visualDiff = $( '<div>' ),
progress = new OO.ui.ProgressBarWidget( { classes: [ 've-init-mw-diffPage-loading' ] } ),
originalUri = new mw.Uri(),
mode = originalUri.query.diffmode || mw.user.options.get( 'visualeditor-diffmode-historical' ) || 'source',
conf = mw.config.get( 'wgVisualEditorConfig' ),
pluginModules = conf.pluginModules.filter( mw.loader.getState );
if ( mode !== 'visual' ) {
// Enforce a valid mode, to avoid visual glitches in button-selection.
mode = 'source';
}
$visualDiffContainer.append(
progress.$element.addClass( 'oo-ui-element-hidden' ),
$visualDiff
);
function onReviewModeButtonSelectSelect( item ) {
var $revSlider = $( '.mw-revslider-container' ),
oldId = mw.config.get( 'wgDiffOldId' ),
newId = mw.config.get( 'wgDiffNewId' ),
uri = new mw.Uri();
var oldPageName, newPageName;
if ( mw.config.get( 'wgCanonicalSpecialPageName' ) !== 'ComparePages' ) {
oldPageName = newPageName = mw.config.get( 'wgRelevantPageName' );
} else {
oldPageName = uri.query.page1;
newPageName = uri.query.page2;
}
mode = item.getData();
var isVisual = mode === 'visual';
mw.user.options.set( 'visualeditor-diffmode-historical', mode );
// Same as ve.init.target.getLocalApi()
new mw.Api().saveOption( 'visualeditor-diffmode-historical', mode );
$visualDiffContainer.toggleClass( 'oo-ui-element-hidden', !isVisual );
$wikitextDiffBody.toggleClass( 'oo-ui-element-hidden', isVisual );
$revSlider.toggleClass( 've-init-mw-diffPage-revSlider-visual', isVisual );
if ( isVisual ) {
// Highlight the headers using the same styles as the diff, to better indicate
// the meaning of headers when not using two-column diff.
$wikitextDiffHeader.find( '#mw-diff-otitle1' ).attr( 'data-diff-action', 'remove' );
$wikitextDiffHeader.find( '#mw-diff-ntitle1' ).attr( 'data-diff-action', 'insert' );
} else {
$wikitextDiffHeader.find( '#mw-diff-otitle1' ).removeAttr( 'data-diff-action' );
$wikitextDiffHeader.find( '#mw-diff-ntitle1' ).removeAttr( 'data-diff-action' );
}
if ( isVisual && !(
lastDiff && lastDiff.oldId === oldId && lastDiff.newId === newId &&
lastDiff.oldPageName === oldPageName && lastDiff.newPageName === newPageName
) ) {
$visualDiff.empty();
progress.$element.removeClass( 'oo-ui-element-hidden' );
// TODO: Load a smaller subset of VE for computing the visual diff
var modulePromise = mw.loader.using( [ 'ext.visualEditor.articleTarget' ].concat( pluginModules ) );
mw.libs.ve.diffLoader.getVisualDiffGeneratorPromise( oldId, newId, modulePromise, oldPageName, newPageName ).then( function ( visualDiffGenerator ) {
// This class is loaded via modulePromise above
// eslint-disable-next-line no-undef
var diffElement = new ve.ui.DiffElement( visualDiffGenerator(), { classes: [ 've-init-mw-diffPage-diff' ] } );
diffElement.$document.addClass( 'mw-parser-output' );
progress.$element.addClass( 'oo-ui-element-hidden' );
$visualDiff.append( diffElement.$element );
lastDiff = {
oldId: oldId,
newId: newId,
oldPageName: oldPageName,
newPageName: newPageName
};
diffElement.positionDescriptions();
}, function ( code, data ) {
mw.notify( new mw.Api().getErrorMessage( data ), { type: 'error' } );
reviewModeButtonSelect.selectItemByData( 'source' );
} );
}
if ( history.replaceState ) {
uri.query.diffmode = mode;
history.replaceState( history.state, document.title, uri );
}
}
mw.hook( 'wikipage.diff' ).add( function () {
$wikitextDiffContainer = $( 'table.diff[data-mw="interface"]' );
$wikitextDiffHeader = $wikitextDiffContainer.find( 'tr.diff-title' )
.add( $wikitextDiffContainer.find( 'td.diff-multi, td.diff-notice' ).parent() );
$wikitextDiffBody = $wikitextDiffContainer.find( 'tr' ).not( $wikitextDiffHeader );
$wikitextDiffContainer.after( $visualDiffContainer );
// The PHP widget was a ButtonGroupWidget, so replace with a
// ButtonSelectWidget instead of infusing.
reviewModeButtonSelect = new OO.ui.ButtonSelectWidget( {
items: [
new OO.ui.ButtonOptionWidget( { data: 'visual', icon: 'eye', label: mw.msg( 'visualeditor-savedialog-review-visual' ) } ),
new OO.ui.ButtonOptionWidget( { data: 'source', icon: 'wikiText', label: mw.msg( 'visualeditor-savedialog-review-wikitext' ) } )
]
} );
reviewModeButtonSelect.on( 'select', onReviewModeButtonSelectSelect );
$( '.ve-init-mw-diffPage-diffMode' ).empty().append( reviewModeButtonSelect.$element );
reviewModeButtonSelect.selectItemByData( mode );
} );
}() );