mediawiki-extensions-Visual.../modules/ve-mw/preinit/ve.init.mw.DiffLoader.js
Bartosz Dziewoński 3f0f302577 Enforce that some files must not use the ve global
Previously, the ve-mw/init/ directory contained two kinds of files:
those that were used when initializing VE, and those that may be
loaded even if VE is not going to be initialized at all. The latter
kind must not use the `ve` global variable.

After moving those files to ve-mw/preinit/ we can enforce this with
.eslintrc.json in that directory. This would have prevented T228684.

(Technically they merely must not use `ve.init`, and may use `ve`,
but that's harder to enforce. We should instead move the few non-init
methods out of `ve`: now, track, trackSubscribe, trackSubscribeAll).

Also, group some files under ve-mw/init/: targets/ now (only)
contains ve.init.mw.Target and its subclasses, apiresponsecache/
now contains ve.init.mw.ApiResponseCache and its subclasses.

Bug: T228684
Change-Id: I945249a27f6a0fa10a432d5c5dc57bc7e0461fd8
2019-10-10 15:15:40 +00:00

109 lines
4.4 KiB
JavaScript

/*!
* VisualEditor MediaWiki DiffLoader.
*
* @copyright 2011-2019 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* Diff loader.
*
* @class mw.libs.ve.diffLoader
* @singleton
*/
( function () {
var revCache = {};
mw.libs.ve = mw.libs.ve || {};
mw.libs.ve.diffLoader = {
/**
* Get a ve.dm.Document model from a Parsoid response
*
* @param {Object} response Parsoid response from the VisualEditor API
* @param {number|null} section Section. Null for the whole document.
* @return {ve.dm.Document|null} Document, or null if an invalid response
*/
getModelFromResponse: function ( response, section ) {
var doc,
// This method is only called after actually loading these, see `parseDocumentModulePromise`
// eslint-disable-next-line no-undef
targetClass = ve.init.mw.ArticleTarget,
// eslint-disable-next-line no-undef
metadataIdRegExp = ve.init.platform.getMetadataIdRegExp(),
data = response ? ( response.visualeditor || response.visualeditoredit ) : null;
if ( data && typeof data.content === 'string' ) {
doc = targetClass.static.parseDocument( data.content, 'visual', section, section !== null );
// Strip RESTBase IDs
Array.prototype.forEach.call( doc.querySelectorAll( '[id^="mw"]' ), function ( element ) {
if ( element.id.match( metadataIdRegExp ) ) {
element.removeAttribute( 'id' );
}
} );
return targetClass.static.createModelFromDom( doc, 'visual' );
}
return null;
},
/**
* Fetch a specific revision from Parsoid as a DM document, and cache in memory
*
* @param {number} revId Revision ID
* @param {string} [pageName] Page name, defaults to wgRelevantPageName
* @param {number|null} [section=null] Section. Null for the whole document.
* @param {jQuery.Promise} [parseDocumentModulePromise] Promise which resolves when Target#parseDocument is available
* @return {jQuery.Promise} Promise which resolves with a document model
*/
fetchRevision: function ( revId, pageName, section, parseDocumentModulePromise ) {
var cacheKey;
pageName = pageName || mw.config.get( 'wgRelevantPageName' );
parseDocumentModulePromise = parseDocumentModulePromise || $.Deferred().resolve().promise();
section = section !== undefined ? section : null;
cacheKey = revId + ( section !== null ? '/' + section : '' );
revCache[ cacheKey ] = revCache[ cacheKey ] ||
mw.libs.ve.targetLoader.requestParsoidData( pageName, { oldId: revId, targetName: 'diff' } ).then( function ( response ) {
return parseDocumentModulePromise.then( function () {
return mw.libs.ve.diffLoader.getModelFromResponse( response, section );
} );
} );
return revCache[ cacheKey ];
},
/**
* Get a visual diff generator promise
*
* @param {number|jQuery.Promise} oldIdOrPromise Old revision ID, or document model promise
* @param {number|jQuery.Promise} newIdOrPromise New revision ID, or document model promise
* @param {jQuery.Promise} [parseDocumentModulePromise] Promise which resolves when Target#parseDocument is available
* @param {string} [oldPageName] Old revision's page name, defaults to wgRelevantPageName
* @param {string} [newPageName] New revision's page name, defaults to oldPageName
* @return {jQuery.Promise} Promise which resolves with a ve.dm.VisualDiff generator function
*/
getVisualDiffGeneratorPromise: function ( oldIdOrPromise, newIdOrPromise, parseDocumentModulePromise, oldPageName, newPageName ) {
var oldRevPromise, newRevPromise;
parseDocumentModulePromise = parseDocumentModulePromise || $.Deferred().resolve().promise();
oldPageName = oldPageName || mw.config.get( 'wgRelevantPageName' );
oldRevPromise = typeof oldIdOrPromise === 'number' ? this.fetchRevision( oldIdOrPromise, oldPageName, null, parseDocumentModulePromise ) : oldIdOrPromise;
newRevPromise = typeof newIdOrPromise === 'number' ? this.fetchRevision( newIdOrPromise, newPageName, null, parseDocumentModulePromise ) : newIdOrPromise;
return $.when( oldRevPromise, newRevPromise, parseDocumentModulePromise ).then( function ( oldDoc, newDoc ) {
// TODO: Differ expects newDoc to be derived from oldDoc and contain all its store data.
// We may want to remove that assumption from the differ?
newDoc.getStore().merge( oldDoc.getStore() );
return function () {
// eslint-disable-next-line no-undef
return new ve.dm.VisualDiff( oldDoc, newDoc );
};
} );
}
};
}() );