Use the new 'difftotextpst' option of prop=revisions API in live preview script
authorMatt Russell <public@matt-russell.com>
Wed, 21 Oct 2015 15:08:34 +0000 (02:08 +1100)
committerDerk-Jan Hartman <hartman.wiki@gmail.com>
Sun, 25 Oct 2015 11:32:25 +0000 (12:32 +0100)
This should improve the diff performance on large pages by a fair amount,
especially on slow connections, as you now just upload the page content once
and then download the diff, rather than having to upload the page content,
download the PST'd page content, re-upload the PST'd page content, and then
finally download the diff.

If there is a summary, the parse request is still performed with just the summary
text, but it is done in parallel to the diff request, and will likely finish
before the diff request anyway, so won't impact the diff performance.
A further improvement could be potentially made, by not sending a summary parse
request when the summary is plain text. This would be fairly easy to detect
(assuming extensions can't modify what is parsed in a summary), just
look for "[[" and "/*".

Also improves the error handling to show errors occurring on the diff request.

Bug: T116178
Change-Id: Ic81bad25ccc8b96c862feb31b7dedd80d1507eeb

resources/src/mediawiki.action/mediawiki.action.edit.preview.js

index 6d0175e..125b1b3 100644 (file)
@@ -8,7 +8,7 @@
         * @param {jQuery.Event} e
         */
        function doLivePreview( e ) {
-               var isDiff, api, request, postData, copySelectors, section,
+               var isDiff, api, parseRequest, diffRequest, postData, copySelectors, section,
                        $wikiPreview, $wikiDiff, $editform, $textbox, $summary, $copyElements, $spinner, $errorBox;
 
                isDiff = ( e.target.name === 'wpDiff' );
                api = new mw.Api();
                postData = {
                        action: 'parse',
-                       uselang: mw.config.get( 'wgUserLanguage' ),
                        title: mw.config.get( 'wgPageName' ),
-                       text: $textbox.textSelection( 'getContents' ),
                        summary: $summary.textSelection( 'getContents' ),
-                       sectionpreview: section !== ''
+                       prop: ''
                };
 
-               if ( section === 'new' ) {
-                       postData.section = 'new';
-                       postData.sectiontitle = postData.summary;
-               }
-
                if ( isDiff ) {
                        $wikiPreview.hide();
 
-                       // First PST the input, then diff it
-                       postData.onlypst = true;
-                       request = api.post( postData );
-                       request.done( function ( response ) {
-                               api.post( {
-                                       action: 'query',
-                                       indexpageids: true,
-                                       prop: 'revisions',
-                                       titles: mw.config.get( 'wgPageName' ),
-                                       rvdifftotext: response.parse.text[ '*' ],
-                                       rvprop: [],
-                                       rvsection: section === '' ? undefined : section
-                               } ).done( function ( response ) {
-                                       try {
-                                               var diffHtml = response.query.pages[ response.query.pageids[ 0 ] ]
-                                                       .revisions[ 0 ].diff[ '*' ];
-                                               $wikiDiff.find( 'table.diff tbody' ).html( diffHtml );
-                                       } catch ( e ) {
-                                               // "result.blah is undefined" error, ignore
-                                               mw.log.warn( e );
-                                       }
-                                       $wikiDiff.show();
-                               } );
+                       if ( postData.summary ) {
+                               parseRequest = api.post( postData );
+                       }
+
+                       diffRequest = api.post( {
+                               action: 'query',
+                               indexpageids: true,
+                               prop: 'revisions',
+                               titles: mw.config.get( 'wgPageName' ),
+                               rvdifftotext: $textbox.textSelection( 'getContents' ),
+                               rvdifftotextpst: true,
+                               rvprop: '',
+                               rvsection: section === '' ? undefined : section
+                       } );
+
+                       // Wait for the summary before showing the diff so the page doesn't jump twice
+                       $.when( diffRequest, parseRequest ).done( function ( response ) {
+                               var diffHtml,
+                                       query = response[ 0 ].query;
+                               try {
+                                       diffHtml = query.pages[ query.pageids[ 0 ] ]
+                                               .revisions[ 0 ].diff[ '*' ];
+                                       $wikiDiff.find( 'table.diff tbody' ).html( diffHtml );
+                               } catch ( e ) {
+                                       // "result.blah is undefined" error, ignore
+                                       mw.log.warn( e );
+                               }
+                               $wikiDiff.show();
                        } );
                } else {
                        $wikiDiff.hide();
+
                        $.extend( postData, {
+                               prop: 'text|displaytitle|modules|jsconfigvars|categorieshtml|templates|langlinks|limitreporthtml',
+                               text: $textbox.textSelection( 'getContents' ),
                                pst: true,
                                preview: true,
-                               prop: 'text|displaytitle|modules|jsconfigvars|categorieshtml|templates|langlinks|limitreporthtml',
-                               disableeditsection: true
+                               sectionpreview: section !== '',
+                               disableeditsection: true,
+                               uselang: mw.config.get( 'wgUserLanguage' )
                        } );
-                       request = api.post( postData );
-                       request.done( function ( response ) {
+                       if ( section === 'new' ) {
+                               postData.section = 'new';
+                               postData.sectiontitle = postData.summary;
+                       }
+
+                       parseRequest = api.post( postData );
+                       parseRequest.done( function ( response ) {
                                var li, newList, $displaytitle, $content, $parent, $list;
                                if ( response.parse.jsconfigvars ) {
                                        mw.config.set( response.parse.jsconfigvars );
                                        $wikiPreview.append( $content );
 
                                        $wikiPreview.show();
-
                                }
                        } );
                }
-               request.done( function ( response ) {
-                       var isSubject = ( section === 'new' ),
+               $.when( parseRequest, diffRequest ).done( function ( parseResp ) {
+                       var parse = parseResp && parseResp[ 0 ].parse,
+                               isSubject = ( section === 'new' ),
                                summaryMsg = isSubject ? 'subject-preview' : 'summary-preview',
                                $summaryPreview = $editform.find( '.mw-summary-preview' ).empty();
-                       if ( response.parse.parsedsummary && response.parse.parsedsummary[ '*' ] !== '' ) {
+                       if ( parse && parse.parsedsummary && parse.parsedsummary[ '*' ] !== '' ) {
                                $summaryPreview.append(
                                        mw.message( summaryMsg ).parse(),
                                        ' ',
                                        $( '<span>' ).addClass( 'comment' ).html(
                                                // There is no equivalent to rawParams
                                                mw.message( 'parentheses' ).escaped()
-                                                       .replace( '$1', response.parse.parsedsummary[ '*' ] )
+                                                       .replace( '$1', parse.parsedsummary[ '*' ] )
                                        )
                                );
                        }
                        mw.hook( 'wikipage.editform' ).fire( $editform );
-               } );
-               request.always( function () {
+               } ).always( function () {
                        $spinner.hide();
                        $copyElements.animate( {
                                opacity: 1
                        }, 'fast' );
-               } );
-               request.fail( function ( code, result ) {
-                       var errorMsg = 'API error: ' +  code;
+               } ).fail( function ( code, result ) {
+                       // This just shows the error for whatever request failed first
+                       var errorMsg = 'API error: ' + code;
                        if ( code === 'http' ) {
                                errorMsg = 'HTTP error: ';
                                if ( result.exception ) {