mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-15 02:23:58 +00:00
Merge "Wikitext mode: Use action=parse for preview"
This commit is contained in:
commit
6f16d02c0c
|
@ -953,21 +953,31 @@ ve.init.mw.ArticleTarget.prototype.onSaveDialogPreview = function () {
|
|||
this.emit( 'savePreview' );
|
||||
this.saveDialog.pushPending();
|
||||
|
||||
var wikitext = this.getDocToSave();
|
||||
if ( this.sectionTitle && this.sectionTitle.getValue() ) {
|
||||
wikitext = '== ' + this.sectionTitle.getValue() + ' ==\n\n' + wikitext;
|
||||
var params = {};
|
||||
|
||||
var sectionTitle = this.sectionTitle && this.sectionTitle.getValue();
|
||||
if ( sectionTitle ) {
|
||||
params.section = 'new';
|
||||
params.sectiontitle = sectionTitle;
|
||||
}
|
||||
if ( mw.config.get( 'wgUserVariant' ) ) {
|
||||
params.variant = mw.config.get( 'wgUserVariant' );
|
||||
}
|
||||
|
||||
api.post( {
|
||||
action: 'visualeditor',
|
||||
paction: 'parsedoc',
|
||||
page: this.getPageName(),
|
||||
wikitext: wikitext,
|
||||
pst: true
|
||||
} ).then( function ( response ) {
|
||||
var baseDoc = target.getSurface().getModel().getDocument().getHtmlDocument();
|
||||
var doc = target.constructor.static.parseDocument( response.visualeditor.content, 'visual' );
|
||||
target.saveDialog.showPreview( doc, baseDoc );
|
||||
api.post( ve.extendObject( params, {
|
||||
action: 'parse',
|
||||
title: this.getPageName(),
|
||||
text: this.getDocToSave(),
|
||||
pst: true,
|
||||
preview: true,
|
||||
sectionpreview: this.section !== null,
|
||||
disableeditsection: true,
|
||||
uselang: mw.config.get( 'wgUserLanguage' ),
|
||||
useskin: mw.config.get( 'skin' ),
|
||||
mobileformat: OO.ui.isMobile(),
|
||||
prop: [ 'text', 'categorieshtml', 'displaytitle', 'subtitle', 'modules', 'jsconfigvars' ]
|
||||
} ) ).then( function ( response ) {
|
||||
target.saveDialog.showPreview( response );
|
||||
}, function ( errorCode, details ) {
|
||||
target.saveDialog.showPreview( target.extractErrorMessages( details ) );
|
||||
} ).always( function () {
|
||||
|
|
|
@ -86,7 +86,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
#catlinks {
|
||||
.ve-init-mw-desktopArticleTarget-originalContent #catlinks {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
|
|
|
@ -214,31 +214,40 @@ mw.libs.ve.fixFragmentLinks = function ( container, docTitle, prefix ) {
|
|||
var docTitleText = docTitle.getPrefixedText();
|
||||
prefix = prefix || '';
|
||||
Array.prototype.forEach.call( container.querySelectorAll( 'a[href*="#"]' ), function ( el ) {
|
||||
var fragment = new mw.Uri( el.href ).fragment,
|
||||
targetData = mw.libs.ve.getTargetDataFromHref( el.href, el.ownerDocument );
|
||||
var fragment = null;
|
||||
if ( el.getAttribute( 'href' )[ 0 ] === '#' ) {
|
||||
// Leagcy parser
|
||||
fragment = el.getAttribute( 'href' ).slice( 1 );
|
||||
} else {
|
||||
// Parsoid HTML
|
||||
var targetData = mw.libs.ve.getTargetDataFromHref( el.href, el.ownerDocument );
|
||||
|
||||
if ( targetData.isInternal ) {
|
||||
var title = mw.Title.newFromText( targetData.title );
|
||||
if ( title && title.getPrefixedText() === docTitleText ) {
|
||||
if ( !fragment ) {
|
||||
// Special case for empty fragment, even if prefix set
|
||||
el.setAttribute( 'href', '#' );
|
||||
} else {
|
||||
if ( prefix ) {
|
||||
var target = container.querySelector( '#' + $.escapeSelector( fragment ) );
|
||||
// There may be multiple links to a specific target, so check the target
|
||||
// hasn't already been fixed (in which case it would be null)
|
||||
if ( target ) {
|
||||
target.setAttribute( 'id', prefix + fragment );
|
||||
target.setAttribute( 'data-mw-id-fixed', '' );
|
||||
}
|
||||
}
|
||||
el.setAttribute( 'href', '#' + prefix + fragment );
|
||||
if ( targetData.isInternal ) {
|
||||
var title = mw.Title.newFromText( targetData.title );
|
||||
if ( title && title.getPrefixedText() === docTitleText ) {
|
||||
fragment = new mw.Uri( el.href ).fragment;
|
||||
}
|
||||
el.removeAttribute( 'target' );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ( fragment !== null ) {
|
||||
if ( !fragment ) {
|
||||
// Special case for empty fragment, even if prefix set
|
||||
el.setAttribute( 'href', '#' );
|
||||
} else {
|
||||
if ( prefix ) {
|
||||
var target = container.querySelector( '#' + $.escapeSelector( fragment ) );
|
||||
// There may be multiple links to a specific target, so check the target
|
||||
// hasn't already been fixed (in which case it would be null)
|
||||
if ( target ) {
|
||||
target.setAttribute( 'id', prefix + fragment );
|
||||
target.setAttribute( 'data-mw-id-fixed', '' );
|
||||
}
|
||||
}
|
||||
el.setAttribute( 'href', '#' + prefix + fragment );
|
||||
}
|
||||
el.removeAttribute( 'target' );
|
||||
}
|
||||
} );
|
||||
// Remove any section heading anchors which weren't fixed above (T218492)
|
||||
Array.prototype.forEach.call( container.querySelectorAll( 'h1, h2, h3, h4, h5, h6' ), function ( el ) {
|
||||
|
@ -314,44 +323,6 @@ mw.libs.ve.getTargetDataFromHref = function ( href, doc ) {
|
|||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand a string of the form jquery.foo,bar|jquery.ui.baz,quux to
|
||||
* an array of module names like [ 'jquery.foo', 'jquery.bar',
|
||||
* 'jquery.ui.baz', 'jquery.ui.quux' ]
|
||||
*
|
||||
* Implementation of ResourceLoaderContext::expandModuleNames
|
||||
* TODO: Consider upstreaming this to MW core.
|
||||
*
|
||||
* @param {string} moduleNames Packed module name list
|
||||
* @return {string[]} Array of module names
|
||||
*/
|
||||
mw.libs.ve.expandModuleNames = function ( moduleNames ) {
|
||||
var modules = [];
|
||||
|
||||
moduleNames.split( '|' ).forEach( function ( group ) {
|
||||
if ( group.indexOf( ',' ) === -1 ) {
|
||||
// This is not a set of modules in foo.bar,baz notation
|
||||
// but a single module
|
||||
modules.push( group );
|
||||
} else {
|
||||
// This is a set of modules in foo.bar,baz notation
|
||||
var matches = group.match( /(.*)\.([^.]*)/ );
|
||||
if ( !matches ) {
|
||||
// Prefixless modules, i.e. without dots
|
||||
modules = modules.concat( group.split( ',' ) );
|
||||
} else {
|
||||
// We have a prefix and a bunch of suffixes
|
||||
var prefix = matches[ 1 ];
|
||||
var suffixes = matches[ 2 ].split( ',' ); // [ 'bar', 'baz' ]
|
||||
suffixes.forEach( function ( suffix ) {
|
||||
modules.push( prefix + '.' + suffix );
|
||||
} );
|
||||
}
|
||||
}
|
||||
} );
|
||||
return modules;
|
||||
};
|
||||
|
||||
/**
|
||||
* Split Parsoid resource name into the href prefix and the page title.
|
||||
*
|
||||
|
|
|
@ -204,107 +204,39 @@ ve.ui.MWSaveDialog.prototype.setDiffAndReview = function ( wikitextDiffPromise,
|
|||
/**
|
||||
* Set preview content and show preview panel.
|
||||
*
|
||||
* @param {HTMLDocument|jQuery} docOrMsg Document to preview, or error message
|
||||
* @param {HTMLDocument} [baseDoc] Base document against which to normalise links, if document provided
|
||||
* @param {Object|jQuery} response action=parse API response, or error message
|
||||
*/
|
||||
ve.ui.MWSaveDialog.prototype.showPreview = function ( docOrMsg, baseDoc ) {
|
||||
var dialog = this;
|
||||
|
||||
if ( docOrMsg instanceof HTMLDocument ) {
|
||||
var modules = [];
|
||||
// Extract required modules for stylesheet tags (avoids re-loading styles)
|
||||
Array.prototype.forEach.call( docOrMsg.head.querySelectorAll( 'link[rel~=stylesheet]' ), function ( link ) {
|
||||
var uri = new mw.Uri( link.href );
|
||||
if ( uri.query.modules ) {
|
||||
modules = modules.concat( mw.libs.ve.expandModuleNames( uri.query.modules ) );
|
||||
}
|
||||
} );
|
||||
// Remove skin-specific modules (T187075 / T185284)
|
||||
modules = modules.filter( function ( module ) {
|
||||
return !/^(skins|mediawiki\.skinning)\./.test( module );
|
||||
} );
|
||||
mw.loader.using( modules );
|
||||
var body = docOrMsg.body;
|
||||
var categories = [];
|
||||
// Take a snapshot of all categories
|
||||
Array.prototype.forEach.call( body.querySelectorAll( 'link[rel~="mw:PageProp/Category"]' ), function ( element ) {
|
||||
categories.push( ve.dm.nodeFactory.createFromElement( ve.dm.MWCategoryMetaItem.static.toDataElement( [ element ] ) ) );
|
||||
} );
|
||||
// Import body to current document, then resolve attributes against original document (parseDocument called #fixBase)
|
||||
document.adoptNode( body );
|
||||
|
||||
// TODO: This code is very similar to ve.ui.PreviewElement+ve.ui.MWPreviewElement
|
||||
ve.resolveAttributes( body, docOrMsg, ve.dm.Converter.static.computedAttributes );
|
||||
|
||||
// Document title will only be set if wikitext contains {{DISPLAYTITLE}}
|
||||
if ( docOrMsg.title ) {
|
||||
// HACK: Parse title as it can contain basic wikitext (T122976)
|
||||
ve.init.target.getContentApi().post( {
|
||||
action: 'parse',
|
||||
title: ve.init.target.getPageName(),
|
||||
prop: 'displaytitle',
|
||||
text: '{{DISPLAYTITLE:' + docOrMsg.title + '}}\n'
|
||||
} ).then( function ( response ) {
|
||||
if ( ve.getProp( response, 'parse', 'displaytitle' ) ) {
|
||||
// eslint-disable-next-line no-jquery/no-html
|
||||
dialog.$previewHeading.html( response.parse.displaytitle );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
// Redirect
|
||||
var $redirect = $( [] );
|
||||
var redirectMeta = body.querySelector( 'link[rel="mw:PageProp/redirect"]' );
|
||||
if ( redirectMeta ) {
|
||||
$redirect = ve.init.mw.ArticleTarget.static.buildRedirectMsg(
|
||||
mw.libs.ve.getTargetDataFromHref(
|
||||
redirectMeta.getAttribute( 'href' ),
|
||||
document
|
||||
).title
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: This won't work with formatted titles (T122976)
|
||||
this.$previewHeading.text( docOrMsg.title || mw.Title.newFromText( ve.init.target.getPageName() ).getPrefixedText() );
|
||||
ve.ui.MWSaveDialog.prototype.showPreview = function ( response ) {
|
||||
if ( response instanceof $ ) {
|
||||
this.$previewViewer.empty().append(
|
||||
// eslint-disable-next-line no-jquery/no-append-html
|
||||
$( '<em>' ).append( response )
|
||||
);
|
||||
} else {
|
||||
var data = response.parse;
|
||||
|
||||
mw.config.set( data.jsconfigvars );
|
||||
mw.loader.using( ( data.modules || [] ).concat( data.modulestyles || [] ) );
|
||||
|
||||
// eslint-disable-next-line no-jquery/no-html
|
||||
this.$previewHeading.html( data.displaytitle );
|
||||
// eslint-disable-next-line no-jquery/no-append-html
|
||||
this.$previewViewer.empty().append(
|
||||
$redirect,
|
||||
// The following classes are used here:
|
||||
// * mw-content-ltr
|
||||
// * mw-content-rtl
|
||||
// eslint-disable-next-line no-jquery/no-append-html
|
||||
$( '<div>' ).addClass( 'mw-content-' + mw.config.get( 'wgVisualEditor' ).pageLanguageDir ).append(
|
||||
body.childNodes
|
||||
)
|
||||
// eslint-disable-next-line no-jquery/no-html
|
||||
$( '<div>' ).addClass( 'mw-content-' + mw.config.get( 'wgVisualEditor' ).pageLanguageDir ).html(
|
||||
data.text
|
||||
),
|
||||
data.categorieshtml
|
||||
);
|
||||
|
||||
ve.targetLinksToNewWindow( this.$previewViewer[ 0 ] );
|
||||
// Add styles so links render with their appropriate classes
|
||||
ve.init.platform.linkCache.styleParsoidElements( this.$previewViewer, baseDoc );
|
||||
mw.libs.ve.fixFragmentLinks( this.$previewViewer[ 0 ], mw.Title.newFromText( ve.init.target.getPageName() ), 'mw-save-preview-' );
|
||||
|
||||
var deferred;
|
||||
if ( categories.length ) {
|
||||
// If there are categories, we need to render them. This involves
|
||||
// a delay, since they might be hidden categories.
|
||||
deferred = ve.init.target.renderCategories( categories ).done( function ( $categories ) {
|
||||
dialog.$previewViewer.append( $categories );
|
||||
|
||||
ve.targetLinksToNewWindow( $categories[ 0 ] );
|
||||
// Add styles so links render with their appropriate classes
|
||||
ve.init.platform.linkCache.styleParsoidElements( $categories, baseDoc );
|
||||
} );
|
||||
} else {
|
||||
deferred = ve.createDeferred().resolve();
|
||||
}
|
||||
deferred.done( function () {
|
||||
// Run hooks so other things can alter the document
|
||||
mw.hook( 'wikipage.content' ).fire( dialog.$previewViewer );
|
||||
} );
|
||||
} else if ( docOrMsg instanceof $ ) {
|
||||
this.$previewViewer.empty().append(
|
||||
// eslint-disable-next-line no-jquery/no-append-html
|
||||
$( '<em>' ).append( docOrMsg )
|
||||
);
|
||||
// Run hooks so other things can alter the document
|
||||
mw.hook( 'wikipage.content' ).fire( this.$previewViewer );
|
||||
}
|
||||
|
||||
this.popPending();
|
||||
|
|
Loading…
Reference in a new issue