2016-05-26 12:08:26 +00:00
|
|
|
/*!
|
|
|
|
* VisualEditor DataModel MWWikitextSurfaceFragment class.
|
|
|
|
*
|
2020-01-08 17:13:04 +00:00
|
|
|
* @copyright 2011-2020 VisualEditor Team and others; see http://ve.mit-license.org
|
2016-05-26 12:08:26 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* DataModel MWWikitextSurfaceFragment.
|
|
|
|
*
|
|
|
|
* @class
|
|
|
|
* @extends ve.dm.SourceSurfaceFragment
|
|
|
|
*
|
|
|
|
* @constructor
|
|
|
|
* @param {ve.dm.Document} doc
|
|
|
|
*/
|
|
|
|
ve.dm.MWWikitextSurfaceFragment = function VeDmMwWikitextSurfaceFragment() {
|
|
|
|
// Parent constructors
|
|
|
|
ve.dm.MWWikitextSurfaceFragment.super.apply( this, arguments );
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Inheritance */
|
|
|
|
|
|
|
|
OO.inheritClass( ve.dm.MWWikitextSurfaceFragment, ve.dm.SourceSurfaceFragment );
|
|
|
|
|
2016-10-03 19:55:16 +00:00
|
|
|
/* Methods */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
|
|
|
ve.dm.MWWikitextSurfaceFragment.prototype.hasMatchingAncestor = function ( type, attributes ) {
|
2021-10-13 12:57:45 +00:00
|
|
|
var nodes = this.getSelectedLeafNodes(),
|
2016-10-03 19:55:16 +00:00
|
|
|
all = !!nodes.length;
|
|
|
|
|
2021-10-13 12:57:45 +00:00
|
|
|
for ( var i = 0, len = nodes.length; i < len; i++ ) {
|
|
|
|
var text = this.document.data.getText( false, nodes[ i ].getRange() );
|
2016-10-03 19:55:16 +00:00
|
|
|
// TODO: Use a registry to do this matching
|
|
|
|
switch ( type ) {
|
|
|
|
case 'paragraph':
|
2022-01-13 11:10:02 +00:00
|
|
|
// Anything but what's matched below
|
2022-03-24 10:20:01 +00:00
|
|
|
all = !/^([ =]|<blockquote>)/.test( text );
|
2016-10-03 19:55:16 +00:00
|
|
|
break;
|
|
|
|
case 'mwPreformatted':
|
|
|
|
all = text.slice( 0, 1 ) === ' ';
|
|
|
|
break;
|
|
|
|
case 'blockquote':
|
|
|
|
all = text.slice( 0, 12 ) === '<blockquote>';
|
|
|
|
break;
|
|
|
|
case 'mwHeading':
|
2022-01-13 11:10:02 +00:00
|
|
|
all = new RegExp( '^={' + attributes.level + '}[^=]' ).test( text ) &&
|
|
|
|
new RegExp( '[^=]={' + attributes.level + '}$' ).test( text );
|
2016-10-03 19:55:16 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
all = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ( !all ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return all;
|
|
|
|
};
|
|
|
|
|
2016-05-26 12:08:26 +00:00
|
|
|
/**
|
|
|
|
* Wrap a text selection.
|
|
|
|
*
|
|
|
|
* If the selection is already identically wrapped it will be unwrapped.
|
|
|
|
*
|
|
|
|
* @param {string} before Text to go before selection
|
|
|
|
* @param {string} after Text to go after selection
|
|
|
|
* @param {Function|string} placeholder Placeholder text to insert at an empty selection
|
2022-02-14 15:18:57 +00:00
|
|
|
* @param {boolean} [forceWrap=false] Force wrapping, even if matching wrapping exists
|
2019-04-16 15:17:29 +00:00
|
|
|
* @return {ve.dm.MWWikitextSurfaceFragment}
|
2016-05-26 12:08:26 +00:00
|
|
|
* @chainable
|
|
|
|
*/
|
|
|
|
ve.dm.MWWikitextSurfaceFragment.prototype.wrapText = function ( before, after, placeholder, forceWrap ) {
|
|
|
|
placeholder = OO.ui.resolveMsg( placeholder );
|
|
|
|
|
|
|
|
function unwrap( fragment ) {
|
|
|
|
var text = fragment.getText();
|
|
|
|
if (
|
|
|
|
( !before || text.slice( 0, before.length ) === before ) &&
|
|
|
|
( !after || text.slice( -after.length ) === after )
|
|
|
|
) {
|
|
|
|
fragment.unwrapText( before.length, after.length );
|
|
|
|
// Just the placeholder left, nothing meaningful was selected so just remove it
|
|
|
|
if ( fragment.getText() === placeholder ) {
|
|
|
|
fragment.removeContent();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !forceWrap && ( unwrap( this ) || unwrap( this.adjustLinearSelection( -before.length, after.length ) ) ) ) {
|
|
|
|
return this;
|
|
|
|
} else {
|
|
|
|
if ( placeholder && this.getSelection().isCollapsed() ) {
|
|
|
|
this.insertContent( placeholder );
|
|
|
|
}
|
2021-10-13 12:57:45 +00:00
|
|
|
var wrappedFragment = this.clone();
|
|
|
|
var wasExcludingInsertions = this.willExcludeInsertions();
|
2016-05-26 12:08:26 +00:00
|
|
|
this.setExcludeInsertions( true );
|
|
|
|
this.collapseToStart().insertContent( before );
|
|
|
|
this.collapseToEnd().insertContent( after );
|
|
|
|
this.setExcludeInsertions( wasExcludingInsertions );
|
|
|
|
return wrappedFragment;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unwrap a fixed amount of text
|
|
|
|
*
|
|
|
|
* @param {number} before Amount of text to remove from start
|
|
|
|
* @param {number} after Amount of text to remove from end
|
2019-04-16 15:17:29 +00:00
|
|
|
* @return {ve.dm.MWWikitextSurfaceFragment}
|
2016-05-26 12:08:26 +00:00
|
|
|
* @chainable
|
|
|
|
*/
|
|
|
|
ve.dm.MWWikitextSurfaceFragment.prototype.unwrapText = function ( before, after ) {
|
|
|
|
this.collapseToStart().adjustLinearSelection( 0, before ).removeContent();
|
|
|
|
this.collapseToEnd().adjustLinearSelection( -after, 0 ).removeContent();
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
2016-12-01 22:47:19 +00:00
|
|
|
ve.dm.MWWikitextSurfaceFragment.prototype.convertToSource = function ( doc ) {
|
2016-05-26 12:08:26 +00:00
|
|
|
if ( !doc.data.hasContent() ) {
|
2019-11-02 05:06:28 +00:00
|
|
|
return ve.createDeferred().resolve( '' ).promise();
|
2016-05-26 12:08:26 +00:00
|
|
|
}
|
|
|
|
|
2021-10-13 12:57:45 +00:00
|
|
|
var wikitextPromise = ve.init.target.getWikitextFragment( doc, false );
|
2016-05-26 12:08:26 +00:00
|
|
|
|
|
|
|
// TODO: Emit an event to trigger the progress bar
|
2021-10-13 12:57:45 +00:00
|
|
|
var progressPromise = ve.init.target.getSurface().createProgress(
|
2016-05-26 12:08:26 +00:00
|
|
|
wikitextPromise, ve.msg( 'visualeditor-generating-wikitext-progress' )
|
2017-12-12 16:22:34 +00:00
|
|
|
).then( function ( progressBar, cancelPromise ) {
|
2016-05-26 12:08:26 +00:00
|
|
|
cancelPromise.fail( function () {
|
|
|
|
wikitextPromise.abort();
|
|
|
|
} );
|
|
|
|
} );
|
|
|
|
|
2019-11-02 16:29:11 +00:00
|
|
|
return ve.promiseAll( [ wikitextPromise, progressPromise ] ).then( function ( wikitext ) {
|
2019-11-02 05:06:28 +00:00
|
|
|
var deferred = ve.createDeferred();
|
2017-12-12 16:22:34 +00:00
|
|
|
setTimeout( function () {
|
2019-11-15 22:13:54 +00:00
|
|
|
if ( wikitext !== undefined ) {
|
|
|
|
deferred.resolve( wikitext );
|
|
|
|
} else {
|
|
|
|
deferred.reject();
|
|
|
|
}
|
2017-12-12 16:22:34 +00:00
|
|
|
}, ve.init.target.getSurface().dialogs.getTeardownDelay() );
|
|
|
|
return deferred.promise();
|
|
|
|
} );
|
2016-05-26 12:08:26 +00:00
|
|
|
};
|
2016-12-01 22:47:19 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritdoc
|
|
|
|
*/
|
|
|
|
ve.dm.MWWikitextSurfaceFragment.prototype.convertFromSource = function ( source ) {
|
2016-12-03 17:18:38 +00:00
|
|
|
var parsePromise;
|
|
|
|
if ( !source ) {
|
2019-11-02 05:06:28 +00:00
|
|
|
parsePromise = ve.createDeferred().resolve(
|
2017-03-02 03:47:23 +00:00
|
|
|
ve.dm.Document.static.newBlankDocument()
|
2016-12-03 17:18:38 +00:00
|
|
|
).promise();
|
|
|
|
} else {
|
2018-04-06 11:30:57 +00:00
|
|
|
parsePromise = ve.init.target.parseWikitextFragment( source, false, this.getDocument() ).then( function ( response ) {
|
2016-12-03 17:18:38 +00:00
|
|
|
return ve.dm.converter.getModelFromDom(
|
|
|
|
ve.createDocumentFromHtml( response.visualeditor.content )
|
|
|
|
);
|
|
|
|
} );
|
|
|
|
}
|
2016-12-01 22:47:19 +00:00
|
|
|
|
2016-12-03 17:12:15 +00:00
|
|
|
// TODO: Show progress bar without breaking WindowAction
|
2018-11-21 12:33:32 +00:00
|
|
|
/*
|
|
|
|
ve.init.target.getSurface().createProgress(
|
|
|
|
parsePromise, ve.msg( 'visualeditor-generating-wikitext-progress' )
|
|
|
|
).done( function ( progressBar, cancelPromise ) {
|
|
|
|
cancelPromise.fail( function () {
|
|
|
|
parsePromise.abort();
|
|
|
|
} );
|
|
|
|
} );
|
|
|
|
*/
|
2016-12-01 22:47:19 +00:00
|
|
|
|
|
|
|
return parsePromise;
|
|
|
|
};
|