mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-09-23 18:28:51 +00:00
Link inspector images and descriptions
Fetches images from PageImages extension and descriptions from Wikibase. Bug: T93693 Bug: T93694 (partial) Change-Id: I1bea6b7b57ab951e79468cfa00e9eecddc113d18
This commit is contained in:
parent
2e96c8c1f3
commit
3963b1daf2
|
@ -381,6 +381,8 @@ class VisualEditorHooks {
|
|||
$vars['wgVisualEditor'] = array(
|
||||
'pageLanguageCode' => $pageLanguage->getHtmlCode(),
|
||||
'pageLanguageDir' => $pageLanguage->getDir(),
|
||||
'usePageImages' => defined( 'PAGE_IMAGES_INSTALLED' ),
|
||||
'usePageDescriptions' => defined( 'WBC_VERSION' ),
|
||||
);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -1133,7 +1133,8 @@ $wgResourceModules += array(
|
|||
'modules/ve-mw/ui/contextitems/ve.ui.MWInternalLinkContextItem.js',
|
||||
),
|
||||
'styles' => array(
|
||||
'modules/ve-mw/ui/styles/widgets/ve.ui.MWLinkTargetInputWidget.css'
|
||||
'modules/ve-mw/ui/styles/widgets/ve.ui.MWLinkTargetInputWidget.css',
|
||||
'modules/ve-mw/ui/styles/widgets/ve.ui.MWInternalLinkMenuOptionWidget.css'
|
||||
),
|
||||
'skinStyles' => array(
|
||||
'default' => array(
|
||||
|
@ -1550,6 +1551,7 @@ $wgResourceModules += array(
|
|||
'modules/ve-mw/ui/styles/ve.ui.Icons.css',
|
||||
),
|
||||
'dependencies' => array(
|
||||
'oojs-ui.styles.icons-content',
|
||||
'oojs-ui.styles.icons-editing-advanced',
|
||||
'oojs-ui.styles.icons-editing-core',
|
||||
'oojs-ui.styles.icons-editing-styling',
|
||||
|
|
|
@ -1158,7 +1158,8 @@
|
|||
"modules/ve-mw/ui/contextitems/ve.ui.MWInternalLinkContextItem.js"
|
||||
],
|
||||
"styles": [
|
||||
"modules/ve-mw/ui/styles/widgets/ve.ui.MWLinkTargetInputWidget.css"
|
||||
"modules/ve-mw/ui/styles/widgets/ve.ui.MWLinkTargetInputWidget.css",
|
||||
"modules/ve-mw/ui/styles/widgets/ve.ui.MWInternalLinkMenuOptionWidget.css"
|
||||
],
|
||||
"skinStyles": {
|
||||
"default": [
|
||||
|
@ -1577,6 +1578,7 @@
|
|||
"modules/ve-mw/ui/styles/ve.ui.Icons.css"
|
||||
],
|
||||
"dependencies": [
|
||||
"oojs-ui.styles.icons-content",
|
||||
"oojs-ui.styles.icons-editing-advanced",
|
||||
"oojs-ui.styles.icons-editing-core",
|
||||
"oojs-ui.styles.icons-editing-styling",
|
||||
|
|
|
@ -79,7 +79,10 @@
|
|||
ve.init.mw.LinkCache.prototype.getRequestPromise = function ( subqueue ) {
|
||||
return new mw.Api().get( {
|
||||
action: 'query',
|
||||
prop: 'info|pageprops',
|
||||
gpslimit: 10,
|
||||
prop: 'info|pageprops|pageimages|pageterms',
|
||||
pithumbsize: 80,
|
||||
pilimit: 10,
|
||||
ppprop: 'disambiguation',
|
||||
titles: subqueue.join( '|' )
|
||||
} );
|
||||
|
@ -93,7 +96,9 @@
|
|||
missing: page.missing !== undefined,
|
||||
redirect: page.redirect !== undefined,
|
||||
// Disambiguator extension
|
||||
disambiguation: page.pageprops && page.pageprops.disambiguation !== undefined
|
||||
disambiguation: page.pageprops && page.pageprops.disambiguation !== undefined,
|
||||
imageUrl: ve.getProp( page, 'thumbnail', 'source' ),
|
||||
description: ve.getProp( page, 'terms', 'description' )
|
||||
};
|
||||
};
|
||||
}() );
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*!
|
||||
* VisualEditor MediaWiki UserInterface MWInternalLinkMenuOptionWidget styles.
|
||||
*
|
||||
* @copyright 2011-2015 VisualEditor Team and others; see AUTHORS.txt
|
||||
* @license The MIT License (MIT); see LICENSE.txt
|
||||
*/
|
||||
|
||||
.ve-ui-mwLinkTargetInputWidget-menu-withImages .ve-ui-mwInternalLinkMenuOptionWidget {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
min-height: 3.75em;
|
||||
margin-left: 3.75em;
|
||||
}
|
||||
|
||||
.ve-ui-mwLinkTargetInputWidget-menu-withImages .ve-ui-mwInternalLinkMenuOptionWidget:not(:last-child) {
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.ve-ui-mwLinkTargetInputWidget-menu-withImages .oo-ui-iconElement .oo-ui-iconElement-icon {
|
||||
display: block;
|
||||
width: 3.75em;
|
||||
height: 3.75em;
|
||||
left: -3.75em;
|
||||
background-color: #ccc;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.ve-ui-mwLinkTargetInputWidget-menu-withImages .oo-ui-iconElement .ve-ui-mwInternalLinkMenuOptionWidget-hasImage {
|
||||
border: 0;
|
||||
background-size: cover;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.ve-ui-mwLinkTargetInputWidget-menu-withImages .ve-ui-mwInternalLinkMenuOptionWidget .oo-ui-labelElement-label {
|
||||
line-height: 3em;
|
||||
}
|
||||
|
||||
.ve-ui-mwInternalLinkMenuOptionWidget-description {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ve-ui-mwLinkTargetInputWidget-menu-withDescriptions .ve-ui-mwInternalLinkMenuOptionWidget .oo-ui-labelElement-label {
|
||||
line-height: 1.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ve-ui-mwLinkTargetInputWidget-menu-withDescriptions .ve-ui-mwInternalLinkMenuOptionWidget-description {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.oo-ui-menuOptionWidget:not(.oo-ui-optionWidget-selected) .ve-ui-mwInternalLinkMenuOptionWidget-description,
|
||||
.oo-ui-menuOptionWidget.oo-ui-optionWidget-highlighted .ve-ui-mwInternalLinkMenuOptionWidget-description {
|
||||
color: #888;
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
/*!
|
||||
* VisualEditor UserInterface MWInternalLinkMenuOptionWidget class
|
||||
* VisualEditor UserInterface MWInternalLinkMenuOptionWidget class.
|
||||
*
|
||||
* @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org
|
||||
* @copyright 2011-2015 VisualEditor Team and others; see AUTHORS.txt
|
||||
* @license The MIT License (MIT); see LICENSE.txt
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -13,10 +14,12 @@
|
|||
* @constructor
|
||||
* @param {Object} [config] Configuration options
|
||||
* @cfg {string} [pagename] Pagename to return the names of internal pages
|
||||
* @cfg {string} [imageUrl] Thumbnail image URL with URL encoding
|
||||
* @cfg {string} [description] Page description
|
||||
*/
|
||||
ve.ui.MWInternalLinkMenuOptionWidget = function VeUiMWInternalLinkMenuOptionWidget( config ) {
|
||||
// Config initialization
|
||||
config = config || {};
|
||||
config = ve.extendObject( { icon: 'article' }, config );
|
||||
|
||||
// Properties
|
||||
this.pagename = config.pagename;
|
||||
|
@ -26,6 +29,23 @@ ve.ui.MWInternalLinkMenuOptionWidget = function VeUiMWInternalLinkMenuOptionWidg
|
|||
|
||||
// Style based on link cache information
|
||||
ve.init.platform.linkCache.styleElement( this.pagename, this.$link );
|
||||
|
||||
// Intialization
|
||||
this.$element.addClass( 've-ui-mwInternalLinkMenuOptionWidget' );
|
||||
|
||||
if ( config.imageUrl ) {
|
||||
this.$icon
|
||||
.addClass( 've-ui-mwInternalLinkMenuOptionWidget-hasImage' )
|
||||
.css( 'background-image', 'url(' + config.imageUrl + ')' );
|
||||
}
|
||||
|
||||
if ( config.description ) {
|
||||
this.$element.append(
|
||||
$( '<span>' )
|
||||
.addClass( 've-ui-mwInternalLinkMenuOptionWidget-description' )
|
||||
.text( config.description )
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/* Inheritance */
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/*!
|
||||
* VisualEditor UserInterface MWLinkMenuOptionWidget class
|
||||
* VisualEditor UserInterface MWLinkMenuOptionWidget class.
|
||||
*
|
||||
* @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org
|
||||
* @copyright 2011-2015 VisualEditor Team and others; see AUTHORS.txt
|
||||
* @license The MIT License (MIT); see LICENSE.txt
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -16,7 +17,7 @@
|
|||
*/
|
||||
ve.ui.MWLinkMenuOptionWidget = function VeUiMWLinkMenuOptionWidget( config ) {
|
||||
// Config initialization
|
||||
config = config || {};
|
||||
config = $.extend( { icon: null }, config );
|
||||
|
||||
// Parent constructor
|
||||
ve.ui.MWLinkMenuOptionWidget.super.call( this, config );
|
||||
|
|
|
@ -33,6 +33,12 @@ ve.ui.MWLinkTargetInputWidget = function VeUiMWLinkTargetInputWidget( config ) {
|
|||
// Initialization
|
||||
this.$element.addClass( 've-ui-mwLinkTargetInputWidget' );
|
||||
this.lookupMenu.$element.addClass( 've-ui-mwLinkTargetInputWidget-menu' );
|
||||
if ( mw.config.get( 'wgVisualEditor' ).usePageImages ) {
|
||||
this.lookupMenu.$element.addClass( 've-ui-mwLinkTargetInputWidget-menu-withImages' );
|
||||
}
|
||||
if ( mw.config.get( 'wgVisualEditor' ).usePageDescriptions ) {
|
||||
this.lookupMenu.$element.addClass( 've-ui-mwLinkTargetInputWidget-menu-withDescriptions' );
|
||||
}
|
||||
|
||||
this.interwikiPrefixes = [];
|
||||
this.interwikiPrefixesPromise = new mw.Api().get( {
|
||||
|
@ -103,8 +109,8 @@ ve.ui.MWLinkTargetInputWidget.prototype.getLookupRequest = function () {
|
|||
var req,
|
||||
widget = this,
|
||||
promiseAbortObject = { abort: function () {
|
||||
// Do nothing. This is just so OOUI doesn't break due to abort being undefined.
|
||||
} };
|
||||
// Do nothing. This is just so OOUI doesn't break due to abort being undefined.
|
||||
} };
|
||||
|
||||
if ( mw.Title.newFromText( this.value ) ) {
|
||||
return this.interwikiPrefixesPromise.then( function () {
|
||||
|
@ -124,7 +130,10 @@ ve.ui.MWLinkTargetInputWidget.prototype.getLookupRequest = function () {
|
|||
generator: 'prefixsearch',
|
||||
gpssearch: widget.value,
|
||||
gpsnamespace: 0,
|
||||
prop: 'info|pageprops',
|
||||
gpslimit: 10,
|
||||
prop: 'info|pageprops|pageimages|pageterms',
|
||||
pithumbsize: 80,
|
||||
pilimit: 10,
|
||||
ppprop: 'disambiguation'
|
||||
} );
|
||||
promiseAbortObject.abort = req.abort.bind( req ); // todo: ew
|
||||
|
@ -155,26 +164,30 @@ ve.ui.MWLinkTargetInputWidget.prototype.getLookupCacheDataFromResponse = functio
|
|||
* @returns {OO.ui.MenuOptionWidget[]} Menu items
|
||||
*/
|
||||
ve.ui.MWLinkTargetInputWidget.prototype.getLookupMenuOptionsFromData = function ( data ) {
|
||||
var i, len, item, pageExistsExact, pageExists, index, matchingPage,
|
||||
var i, len, item, pageExistsExact, pageExists, index, matchingPage, linkData,
|
||||
items = [],
|
||||
existingPages = [],
|
||||
matchingPages = [],
|
||||
disambigPages = [],
|
||||
redirectPages = [],
|
||||
titleObj = mw.Title.newFromText( this.value ),
|
||||
linkCacheUpdate = {};
|
||||
links = {};
|
||||
|
||||
for ( index in data ) {
|
||||
matchingPage = data[index];
|
||||
linkCacheUpdate[matchingPage.title] = { missing: false, redirect: false, disambiguation: false };
|
||||
links[matchingPage.title] = {
|
||||
missing: false, redirect: false, disambiguation: false,
|
||||
imageUrl: ve.getProp( matchingPage, 'thumbnail', 'source' ),
|
||||
description: ve.getProp( matchingPage, 'terms', 'description' )
|
||||
};
|
||||
existingPages.push( matchingPage.title );
|
||||
|
||||
if ( matchingPage.redirect !== undefined ) {
|
||||
redirectPages.push( matchingPage.title );
|
||||
linkCacheUpdate[matchingPage.title].redirect = true;
|
||||
links[matchingPage.title].redirect = true;
|
||||
} else if ( matchingPage.pageprops !== undefined && matchingPage.pageprops.disambiguation !== undefined ) {
|
||||
disambigPages.push( matchingPage.title );
|
||||
linkCacheUpdate[matchingPage.title].disambiguation = true;
|
||||
links[matchingPage.title].disambiguation = true;
|
||||
} else {
|
||||
matchingPages.push( matchingPage.title );
|
||||
}
|
||||
|
@ -188,10 +201,10 @@ ve.ui.MWLinkTargetInputWidget.prototype.getLookupMenuOptionsFromData = function
|
|||
);
|
||||
|
||||
if ( !pageExists ) {
|
||||
linkCacheUpdate[this.value] = { missing: true, redirect: false, disambiguation: false };
|
||||
links[this.value] = { missing: true, redirect: false, disambiguation: false };
|
||||
}
|
||||
|
||||
ve.init.platform.linkCache.set( linkCacheUpdate );
|
||||
ve.init.platform.linkCache.set( links );
|
||||
|
||||
// External link
|
||||
if ( ve.init.platform.getExternalLinkUrlProtocolsRegExp().test( this.value ) ) {
|
||||
|
@ -233,17 +246,19 @@ ve.ui.MWLinkTargetInputWidget.prototype.getLookupMenuOptionsFromData = function
|
|||
if ( matchingPages && matchingPages.length ) {
|
||||
items.push( new OO.ui.MenuSectionOptionWidget( {
|
||||
data: 'matchingPages',
|
||||
label: ve.msg( 'visualeditor-linkinspector-suggest-matching-page',
|
||||
matchingPages.length )
|
||||
label: ve.msg( 'visualeditor-linkinspector-suggest-matching-page', matchingPages.length )
|
||||
} ) );
|
||||
// Offer the exact text as a suggestion if the page exists
|
||||
if ( pageExists && !pageExistsExact ) {
|
||||
matchingPages.unshift( this.value );
|
||||
}
|
||||
for ( i = 0, len = matchingPages.length; i < len; i++ ) {
|
||||
linkData = links[matchingPages[i]] || {};
|
||||
items.push( new ve.ui.MWInternalLinkMenuOptionWidget( {
|
||||
data: this.getInternalLinkAnnotationFromTitle( matchingPages[i] ),
|
||||
pagename: matchingPages[i]
|
||||
pagename: matchingPages[i],
|
||||
imageUrl: linkData.imageUrl,
|
||||
description: linkData.description
|
||||
} ) );
|
||||
}
|
||||
}
|
||||
|
@ -255,9 +270,12 @@ ve.ui.MWLinkTargetInputWidget.prototype.getLookupMenuOptionsFromData = function
|
|||
label: ve.msg( 'visualeditor-linkinspector-suggest-disambig-page', disambigPages.length )
|
||||
} ) );
|
||||
for ( i = 0, len = disambigPages.length; i < len; i++ ) {
|
||||
linkData = links[disambigPages[i]] || {};
|
||||
items.push( new ve.ui.MWInternalLinkMenuOptionWidget( {
|
||||
data: this.getInternalLinkAnnotationFromTitle( disambigPages[i] ),
|
||||
pagename: disambigPages[i]
|
||||
pagename: disambigPages[i],
|
||||
imageUrl: linkData.imageUrl,
|
||||
description: linkData.description
|
||||
} ) );
|
||||
}
|
||||
}
|
||||
|
@ -269,10 +287,10 @@ ve.ui.MWLinkTargetInputWidget.prototype.getLookupMenuOptionsFromData = function
|
|||
label: ve.msg( 'visualeditor-linkinspector-suggest-redirect-page', redirectPages.length )
|
||||
} ) );
|
||||
for ( i = 0, len = redirectPages.length; i < len; i++ ) {
|
||||
items.push( new OO.ui.MenuOptionWidget( {
|
||||
items.push( new ve.ui.MWInternalLinkMenuOptionWidget( {
|
||||
data: this.getInternalLinkAnnotationFromTitle( redirectPages[i] ),
|
||||
rel: 'redirectPage',
|
||||
label: redirectPages[i]
|
||||
// TODO: Add description based on redirect target
|
||||
} ) );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue