Cleanup getDocToSave API and use in source mode

Instead of getting wikitext from the HTML, which is probably
slower and leads to issues with the whitespace stripping hack,
override getDocToSave and get text from the linmod directly.

Bug: T144621
Change-Id: I6b6cf16ee8f3720398ba8f5c85e7715c2e68329f
This commit is contained in:
Ed Sanders 2016-09-02 12:06:04 -07:00
parent 4fbe06a15c
commit d0bb5511a5
3 changed files with 77 additions and 48 deletions

View file

@ -641,7 +641,6 @@ ve.init.mw.DesktopArticleTarget.prototype.cancel = function ( trackMechanism ) {
}
target.clearState();
target.docToSave = null;
target.initialEditSummary = new mw.Uri().query.summary;
target.deactivating = false;
@ -1550,7 +1549,7 @@ ve.init.mw.DesktopArticleTarget.prototype.switchToWikitextEditor = function ( di
} );
} else {
this.serialize(
this.docToSave || this.getSurface().getDom(),
this.getDocToSave(),
function ( wikitext ) {
ve.track( 'mwedit.abort', { type: 'switchwith', mechanism: 'navigate' } );
target.submitWithSaveFields( { wpDiff: 1, wpAutoSummary: '' }, wikitext );

View file

@ -47,7 +47,7 @@ ve.init.mw.DesktopWikitextArticleTarget.prototype.switchToWikitextEditor = funct
var dataPromise,
target = this;
this.serialize( this.docToSave || this.getSurface().getDom() );
this.serialize( this.getDocToSave() );
dataPromise = this.serializing.then( function ( response ) {
// HACK
var data = response.visualeditor;
@ -71,16 +71,16 @@ ve.init.mw.DesktopWikitextArticleTarget.prototype.switchToWikitextEditor = funct
ve.init.mw.DesktopWikitextArticleTarget.prototype.switchToVisualEditor = function () {
var dataPromise;
this.setMode( 'visual' );
dataPromise = mw.libs.ve.targetLoader.requestParsoidData(
this.pageName,
this.revid,
this.constructor.name,
this.edited,
this.getWikitextFromDocument( this.getSurface().getDom() )
this.getDocToSave()
);
this.setMode( 'visual' );
this.reloadSurface( dataPromise );
};
@ -259,33 +259,47 @@ ve.init.mw.DesktopWikitextArticleTarget.prototype.prepareCacheKey = function ()
// else: No need, just wikitext
};
/**
* @inheritdoc
*/
ve.init.mw.DesktopWikitextArticleTarget.prototype.createDocToSave = function () {
var i, l, text, data;
if ( this.mode !== 'source' ) {
// Parent method
return ve.init.mw.DesktopWikitextArticleTarget.super.prototype.createDocToSave.apply( this, arguments );
}
text = '';
data = this.getSurface().getModel().getDocument().data.data;
for ( i = 0, l = data.length; i < l; i++ ) {
if ( data[ i ].type === '/paragraph' && data[ i + 1 ].type === 'paragraph' ) {
text += '\n';
} else if ( !data[ i ].type ) {
text += data[ i ];
}
}
return text;
};
/**
* @inheritdoc
*/
ve.init.mw.DesktopWikitextArticleTarget.prototype.tryWithPreparedCacheKey = function ( doc, options ) {
var data;
if ( this.mode === 'source' ) {
data = ve.extendObject( {}, options, { format: 'json' } );
data.wikitext = this.getWikitextFromDocument( doc );
return new mw.Api().post( data, { contentType: 'multipart/form-data' } );
return new mw.Api().post( ve.extendObject( {}, options, {
wikitext: doc,
format: 'json'
} ),
{ contentType: 'multipart/form-data' }
);
} else {
// Parent method
return ve.init.mw.DesktopWikitextArticleTarget.super.prototype.tryWithPreparedCacheKey.apply( this, arguments );
}
};
/**
* Get wikitext for the whole document
*
* @param {ve.dm.Document} doc Document
* @return {string} Wikitext
*/
ve.init.mw.DesktopWikitextArticleTarget.prototype.getWikitextFromDocument = function ( doc ) {
return Array.prototype.map.call( doc.body.children, function ( p ) { return p.innerText; } ).join( '\n' );
};
/* Registration */
ve.init.mw.targetFactory.register( ve.init.mw.DesktopWikitextArticleTarget );

View file

@ -893,9 +893,9 @@ ve.init.mw.ArticleTarget.prototype.onSaveDialogReview = function () {
this.saveDialog.pushPending();
if ( this.pageExists ) {
// Has no callback, handled via target.showChangesDiff
this.showChanges( this.docToSave );
this.showChanges( this.getDocToSave() );
} else {
this.serialize( this.docToSave, this.onSaveDialogReviewComplete.bind( this ) );
this.serialize( this.getDocToSave(), this.onSaveDialogReviewComplete.bind( this ) );
}
} else {
this.saveDialog.swapPanel( 'review' );
@ -924,7 +924,7 @@ ve.init.mw.ArticleTarget.prototype.onSaveDialogReviewComplete = function ( wikit
ve.init.mw.ArticleTarget.prototype.onSaveDialogResolveConflict = function () {
// Get Wikitext from the DOM, and set up a submit call when it's done
this.serialize(
this.docToSave,
this.getDocToSave(),
this.submitWithSaveFields.bind( this, { wpSave: 1 } )
);
};
@ -946,21 +946,6 @@ ve.init.mw.ArticleTarget.prototype.onSaveDialogRetry = function () {
* @fires saveWorkflowEnd
*/
ve.init.mw.ArticleTarget.prototype.onSaveDialogClose = function () {
var target = this;
function clear() {
target.docToSave = null;
target.clearPreparedCacheKey();
}
// Clear the cached HTML and cache key once the document changes
if ( this.getSurface() ) {
this.getSurface().getModel().getDocument().once( 'transact', clear );
this.getSurface().once( 'destroy', clear );
} else {
clear();
}
this.emit( 'saveWorkflowEnd' );
};
@ -1036,6 +1021,43 @@ ve.init.mw.ArticleTarget.prototype.clearState = function () {
*/
ve.init.mw.ArticleTarget.prototype.editSource = null;
/**
* Get a document to save, cached until the surface is modified
*
* The default implementation returns an HTMLDocument, but other targets
* may use a different document model (e.g. plain text for source mode).
*
* @return {Object} Document to save
*/
ve.init.mw.ArticleTarget.prototype.getDocToSave = function () {
var surface;
if ( !this.docToSave ) {
this.docToSave = this.createDocToSave();
// Cache clearing events
surface = this.getSurface();
surface.getModel().getDocument().once( 'transact', this.clearDocToSave.bind( this ) );
surface.once( 'destroy', this.clearDocToSave.bind( this ) );
}
return this.docToSave;
};
/**
* Create a document to save
*
* @return {Object} Document to save
*/
ve.init.mw.ArticleTarget.prototype.createDocToSave = function () {
return this.getSurface().getDom();
};
/**
* Clear the document to save from the cache
*/
ve.init.mw.ArticleTarget.prototype.clearDocToSave = function () {
this.docToSave = null;
this.clearPreparedCacheKey();
};
/**
* Serialize the current document and store the result in the serialization cache on the server.
*
@ -1278,10 +1300,7 @@ ve.init.mw.ArticleTarget.prototype.onSaveDialogSave = function ( saveDeferred )
* @param {Object} saveOptions Save options
*/
ve.init.mw.ArticleTarget.prototype.startSave = function ( saveOptions ) {
if ( !this.docToSave ) {
this.docToSave = this.getSurface().getDom();
}
this.save( this.docToSave, saveOptions );
this.save( this.getDocToSave(), saveOptions );
};
/**
@ -1606,10 +1625,7 @@ ve.init.mw.ArticleTarget.prototype.showSaveDialog = function () {
this.emit( 'saveWorkflowBegin' );
// Preload the serialization
if ( !this.docToSave ) {
this.docToSave = this.getSurface().getDom();
}
this.prepareCacheKey( this.docToSave );
this.prepareCacheKey( this.getDocToSave() );
// Connect events to save dialog
this.getSurface().getDialogs().getWindow( 'mwSave' ).done( function ( win ) {