Use href attribute to calculate titles

This is needed for wikis that use LanguageConverter, since the title
attribute is converted to the user's variant, and the canonical title is
needed for the API unless converttitles is specified.

For filtering, instead of comparing linkHref and expectedHref, filter
out links that have other query parameters or aren't in content
namespaces.

Bug: T93605
Change-Id: I5534753307ed5e1d4b27c52c616fd143b2a397e1
This commit is contained in:
wctaiwan 2015-03-25 16:53:27 -04:00
parent 56453bc7b1
commit 642bdf013e
5 changed files with 91 additions and 11 deletions

View file

@ -52,11 +52,13 @@ class PopupsHooks {
public static function onResourceLoaderRegisterModules( ResourceLoader $rl ) {
$moduleDependencies = array(
'mediawiki.api',
'mediawiki.Title',
'mediawiki.jqueryMsg',
'mediawiki.Uri',
'moment',
'jquery.jStorage',
'jquery.client',
'jquery.mwExtension',
);
// If EventLogging is present, add the schema as a dependency.
@ -121,7 +123,10 @@ class PopupsHooks {
*/
public static function onResourceLoaderTestModules( array &$testModules, ResourceLoader &$resourceLoader ) {
$testModules['qunit']['ext.popups.tests'] = array(
'scripts' => array( 'tests/qunit/ext.popups.renderer.article.test.js' ),
'scripts' => array(
'tests/qunit/ext.popups.renderer.article.test.js',
'tests/qunit/ext.popups.core.test.js',
),
'dependencies' => array( 'ext.popups' ),
'localBasePath' => __DIR__,
'remoteExtPath' => 'Popups',

View file

@ -145,21 +145,63 @@
} );
};
/**
* Given an href string for the local wiki, return the title, or undefined if
* the link is external, has extra query parameters, or contains no title.
*
* Note that the returned title is not sanitized (may contain underscores).
*
* @param {string} href
* @return {string|undefined}
*/
mw.popups.getTitle = function ( href ) {
var title, titleRegex, matches,
linkHref = new mw.Uri( href );
// External links
if ( linkHref.host !== location.hostname ) {
return undefined;
}
if ( linkHref.query.hasOwnProperty( 'title' ) ) {
// linkHref is not a pretty URL, e.g. /w/index.php?title=Foo
title = linkHref.query.title;
// Return undefined if there are query parameters other than title
delete linkHref.query.title;
return $.isEmptyObject( linkHref.query ) ? title : undefined;
} else {
// linkHref is a pretty URL, e.g. /wiki/Foo
// Return undefined if there are any query parameters
if ( !$.isEmptyObject( linkHref.query ) ) {
return undefined;
}
titleRegex = new RegExp( $.escapeRE( mw.config.get( 'wgArticlePath' ) )
.replace( '\\$1', '(.+)' ) );
matches = titleRegex.exec( linkHref.path );
return matches ? decodeURIComponent( matches[1] ) : undefined;
}
};
/**
* Returns links that can have Popups
*
* @method selectPopupElements
*/
mw.popups.selectPopupElements = function () {
var contentNamespaces = mw.config.get( 'wgContentNamespaces' );
return mw.popups.$content
.find( 'a[href][title]:not(' + mw.popups.IGNORE_CLASSES.join(', ') + ')' )
.filter( function () {
var linkHref = new mw.Uri( this.href ),
expectedHref = new mw.Uri( mw.util.getUrl( this.title ) );
// don't compare fragment to display popups on anchored page links
linkHref.fragment = undefined;
return linkHref.toString() === expectedHref.toString();
var title,
titleText = mw.popups.getTitle( this.href );
if ( !titleText ) {
return false;
}
// Is titleText in a content namespace?
title = mw.Title.newFromText( titleText );
return title && ( $.inArray( title.namespace, contentNamespaces ) >= 0 );
} );
};

View file

@ -32,9 +32,8 @@
* @return {jQuery.Promise}
*/
article.init = function ( link ) {
var
href = link.attr( 'href' ),
title = link.data( 'title' ),
var href = link.attr( 'href' ),
title = mw.popups.getTitle( href ),
deferred = $.Deferred();
if ( !title ) {

View file

@ -0,0 +1,33 @@
( function ( $, mw ) {
QUnit.module( 'ext.popups.core', QUnit.newMwEnvironment( {
config: {
wgArticlePath: '/wiki/$1'
}
} ) );
QUnit.test( 'getTitle', function ( assert ) {
var cases, i, expected, actual;
QUnit.expect( 10 );
cases = [
[ '/wiki/Foo', 'Foo' ],
[ '/wiki/Foo#Bar', 'Foo' ],
[ '/wiki/Foo?oldid=1', undefined ],
[ '/wiki/%E6%B8%AC%E8%A9%A6', '測試' ],
[ '/w/index.php?title=Foo', 'Foo' ],
[ '/w/index.php?title=Foo#Bar', 'Foo' ],
[ '/w/Foo?title=Foo&action=edit', undefined ],
[ '/w/index.php?title=%E6%B8%AC%E8%A9%A6', '測試' ],
[ '/w/index.php?oldid=1', undefined ],
[ '/Foo', undefined ]
];
for ( i = 0; i < cases.length; i++ ) {
expected = cases[i][1];
actual = mw.popups.getTitle( cases[i][0] );
assert.equal( actual, expected );
}
} );
} ) ( jQuery, mediaWiki );

View file

@ -1,6 +1,7 @@
( function ( $, mw ) {
QUnit.module( 'ext.popups' );
QUnit.module( 'ext.popups.renderer.article', QUnit.newMwEnvironment() );
QUnit.test( 'render.article.getProcessedElements', function ( assert ) {
QUnit.expect( 13 );