Take over extra links to add a new topic added by gadgets/templates

* Move getTitleFromUrl() from parser to utils. It's a generic method,
  the PHP equivalent is already in utils.

Bug: T277371
Change-Id: Id960e5f60af02bdeb0a3a68f43b7a695eb035139
This commit is contained in:
Bartosz Dziewoński 2021-06-24 21:10:40 +02:00
parent dce09e61b7
commit f35bf487ef
3 changed files with 75 additions and 34 deletions

View file

@ -495,36 +495,6 @@ Parser.prototype.findTimestamp = function ( node, timestampRegexps ) {
return null;
};
/**
* Get a MediaWiki page title from a URL.
*
* @private
* @param {string} url
* @return {mw.Title|null} Page title, or null if this isn't a link to a page
*/
function getTitleFromUrl( url ) {
try {
url = new mw.Uri( url );
} catch ( err ) {
// T106244: URL encoded values using fallback 8-bit encoding (invalid UTF-8) cause mediawiki.Uri to crash
return null;
}
if ( url.query.title ) {
return mw.Title.newFromText( url.query.title );
}
var articlePathRegexp = new RegExp(
mw.util.escapeRegExp( mw.config.get( 'wgArticlePath' ) )
.replace( mw.util.escapeRegExp( '$1' ), '(.*)' )
);
var match;
if ( ( match = url.path.match( articlePathRegexp ) ) ) {
return mw.Title.newFromText( decodeURIComponent( match[ 1 ] ) );
}
return null;
}
/**
* Given a link node (`<a>`), if it's a link to a user-related page, return their username.
*
@ -532,7 +502,7 @@ function getTitleFromUrl( url ) {
* @return {string|null}
*/
function getUsernameFromLink( link ) {
var title = getTitleFromUrl( link.href );
var title = utils.getTitleFromUrl( link.href );
if ( !title ) {
return null;
}

View file

@ -6,8 +6,10 @@ function ReplyLinksController( $pageContainer ) {
OO.EventEmitter.call( this );
this.$pageContainer = $pageContainer;
this.$body = $( document.body );
this.onReplyLinkClickHandler = this.onReplyLinkClick.bind( this );
this.onAddSectionLinkClickHandler = this.onAddSectionLinkClick.bind( this );
this.onAnyLinkClickHandler = this.onAnyLinkClick.bind( this );
// Reply links
this.$replyLinks = $pageContainer.find( 'a.ext-discussiontools-init-replylink-reply[data-mw-comment]' );
@ -24,6 +26,10 @@ function ReplyLinksController( $pageContainer ) {
if ( $addSectionTab.length && pageExists ) {
this.$addSectionLink = $addSectionTab.find( 'a' );
this.$addSectionLink.on( 'click keypress', this.onAddSectionLinkClickHandler );
// Handle events on all links that potentially open the new section interface,
// including links in the page content (from templates) or from gadgets.
this.$body.on( 'click keypress', 'a:not( [data-mw-comment] )', this.onAnyLinkClickHandler );
}
}
}
@ -52,14 +58,47 @@ ReplyLinksController.prototype.onAddSectionLinkClick = function ( e ) {
if ( !this.isActivationEvent( e ) ) {
return;
}
e.preventDefault();
// Disable VisualEditor's new section editor (in wikitext mode / NWE), to allow our own.
// We do this on first click, because we don't control the order in which our code and NWE code
// runs, so its event handlers may not be registered yet.
$( e.target ).closest( '#ca-addsection' ).off( '.ve-target' );
this.emit( 'link-click', utils.NEW_TOPIC_COMMENT_ID, $( e.target ) );
// onAnyLinkClick() will also handle clicks on this element, so we don't emit() here to avoid
// doing it twice.
};
ReplyLinksController.prototype.onAnyLinkClick = function ( e ) {
// Check query parameters to see if this is really a new topic link
var href = $( e.currentTarget ).attr( 'href' );
var uri;
try {
uri = new mw.Uri( href, { arrayParams: true } );
} catch ( err ) {
// T106244: URL encoded values using fallback 8-bit encoding (invalid UTF-8) cause mediawiki.Uri to crash
return;
}
if ( ( uri.query.action !== 'edit' && uri.query.veaction !== 'editsource' ) || uri.query.section !== 'new' ) {
// Not a link to add a new topic
return;
}
var title = utils.getTitleFromUrl( href );
if ( !title || title.getPrefixedDb() !== mw.config.get( 'wgRelevantPageName' ) ) {
// Link to add a section on another page, not supported yet (T282205)
return;
}
if ( uri.query.editintro || uri.query.preload || uri.query.preloadparams || uri.query.preloadtitle ) {
// Adding a new topic with preloaded text is not supported yet (T269310)
return;
}
if ( !this.isActivationEvent( e ) ) {
return;
}
e.preventDefault();
this.emit( 'link-click', utils.NEW_TOPIC_COMMENT_ID, $( e.currentTarget ) );
};
ReplyLinksController.prototype.isActivationEvent = function ( e ) {
@ -126,6 +165,7 @@ ReplyLinksController.prototype.teardown = function () {
this.$replyLinks.off( 'click keypress', this.onReplyLinkClickHandler );
this.$addSectionLink.off( 'click keypress', this.onAddSectionLinkClickHandler );
this.$body.off( 'click keypress', 'a:not( [data-mw-comment] )', this.onAnyLinkClickHandler );
};
module.exports = ReplyLinksController;

View file

@ -360,6 +360,36 @@ function getFullyCoveredSiblings( item ) {
return null;
}
/**
* Get a MediaWiki page title from a URL.
*
* @private
* @param {string} url
* @return {mw.Title|null} Page title, or null if this isn't a link to a page
*/
function getTitleFromUrl( url ) {
try {
url = new mw.Uri( url );
} catch ( err ) {
// T106244: URL encoded values using fallback 8-bit encoding (invalid UTF-8) cause mediawiki.Uri to crash
return null;
}
if ( url.query.title ) {
return mw.Title.newFromText( url.query.title );
}
var articlePathRegexp = new RegExp(
mw.util.escapeRegExp( mw.config.get( 'wgArticlePath' ) )
.replace( mw.util.escapeRegExp( '$1' ), '(.*)' )
);
var match;
if ( ( match = url.path.match( articlePathRegexp ) ) ) {
return mw.Title.newFromText( decodeURIComponent( match[ 1 ] ) );
}
return null;
}
/**
* Traverse the document in depth-first order, calling the callback whenever entering and leaving
* a node. The walk starts before the given node and ends when callback returns a truthy value, or
@ -439,6 +469,7 @@ module.exports = {
getTranscludedFromElement: getTranscludedFromElement,
getHeadlineNodeAndOffset: getHeadlineNodeAndOffset,
htmlTrim: htmlTrim,
getTitleFromUrl: getTitleFromUrl,
linearWalk: linearWalk,
linearWalkBackwards: linearWalkBackwards
};