Մասնակից:Putnik/Gadget-wikidataInfoboxExport.js
Արտաքին տեսք
Ծանուցում. Հիշելուց հետո կատարված փոփոխությունները տեսնելու համար մաքրեք ձեր զննարկիչի հիշապահեստը. Mozilla / Firefox / Safari՝ Ctrl+Shift+R (Cmd+Shift+R Mac OS X-ում) Konqueror՝ F5 Opera՝ Tools→Preferences ընտրացանկից։ Internet Explorer՝ Ctrl+F5
/**
* Быстрый экспорт информации из карточек в Викиданные.
* Вызов окна экспорта по двойному клику.
*/
( function ( mw, $ ) {
var wdeConfig = {
version: '1.18.1',
languages: [ 'en' ],
references: {
// взято из = армянская Википедия
P143: [ {
snaktype: 'value',
property: 'P143',
datavalue: {
type: 'wikibase-entityid',
value: { id: 'Q1975217' }
}
} ]
},
units: {
Q531: { search: ['լուսային տարի'] },
Q4916: { search: ['^€', '^EUR'] },
Q4917: { search: ['^(?:-|US)?\\$', 'դոլար(?:\\sԱՄՆ)?', '$', 'ԱՄՆ դոլար'] },
Q7727: { search: ['րոպե'] },
Q8146: { search: ['իեն'] },
Q11573: { search: ['մետր'] },
Q25344: { search: ['^CHF'] },
Q41044: { search: ['ռուբլի'] },
Q81292: { search: ['ակր'] },
},
reCirca: /(?:~|մոտ(?:ավորապես)?\.?)/,
reBCE: 'до\\s\+н\\.\\s\*э\\.?\\s\*$',
reCE: 'н\\.\\s\*э\\.?\\s\*$',
misLang: {
ady: 'Q27776',
ain: 'Q20968488',
alt: 'Q1991779',
atv: 'Q2640863',
ckt: 'Q33170',
enf: 'Q29942',
evn: 'Q30004',
inh: 'Q33509',
izh: 'Q33559',
jdt: 'Q56495',
kjh: 'Q33575',
krl: 'Q33557',
kum: 'Q36209',
orv: 'Q35228',
otk: 'Q34988',
pdt: 'Q1751432',
sjd: 'Q33656',
sjt: 'Q36656',
sma: 'Q13293',
vot: 'Q32858',
yrk: 'Q36452'
}
};
var api;
var wdApi;
var wdeBaseRevId;
var wdePropertyIds = [ 'P2076', 'P2077' ]; // температура и давление для квалификаторов
var wdeTypesMapping = {
'commonsMedia': 'string',
'external-id': 'string',
'url': 'string',
'wikibase-item': 'wikibase-entityid'
};
var wdeAlreadyExistingItems = {};
var wdeWindowManager;
var centuries = [ 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII',
'VIII', 'IX', 'X', 'XI', 'XII', 'XIII', 'XIV', 'XV',
'XVI', 'XVII', 'XVIII', 'XIX', 'XX', 'XXI', 'XXII' ];
/**
* Сравнивает значение из карточки и в Викиданных
*/
var wdeCanExportValue = function ( $field, claims, callbackIfCan ) {
if ( !claims || !( claims.length ) ) {
// не можем экспортировать только если это крупное изображение из ru-wiki
if ( !( $field.find( '.image img[src*="/wikipedia/' + wdeConfig.language + '/"]' ).width() >= 80 ) ) {
callbackIfCan();
}
return;
}
switch ( claims[ 0 ].mainsnak.datatype ) {
case 'quantity':
for ( var i = 0; i < claims.length; i++ ) {
var parsedTime = wdeCreateTimeSnak( ( $field.text().match( /\(([^)]*\d\d\d\d)[,)\s]/ ) || [] )[ 1 ] );
if ( parsedTime && ( claims[ i ].qualifiers || {} ).P585 ) {
var claimPrecision = claims[ i ].qualifiers.P585[ 0 ].datavalue.value.precision;
if ( parsedTime.precision < claimPrecision ) {
claims[ i ].qualifiers.P585[ 0 ].datavalue.value.precision = parsedTime.precision;
} else if ( parsedTime.precision > claimPrecision ) { // FIXME: потом уточнить в wd дату
parsedTime.precision = claimPrecision;
}
var p585 = parsedTime ? wdeFormatDataValue( {
type: 'time',
value: parsedTime
} )[ 0 ].innerText : '';
if ( wdeFormatDataValue( claims[ i ].qualifiers.P585[ 0 ].datavalue )[ 0 ].innerText !== p585 ) {
claims[ i ].qualifiers.P585[ 0 ].datavalue.value.precision = claimPrecision;
continue;
}
}
return;
}
callbackIfCan( true );
break;
case 'wikibase-item':
value = wdeParseItems( $field, $field, function ( values ) {
var duplicates = [];
for ( var i = 0; i < values.length; i++ ) {
for ( var j = 0; j < claims.length; j++ ) {
if ( values[ i ].wd.value.id === claims[ j ].mainsnak.datavalue.value.id ) {
duplicates.push( values[ i ].wd.value.id );
}
}
}
if ( duplicates.length < values.length ) {
if ( duplicates.length > 0 ) {
var propertyId = claims[ 0 ].mainsnak.property;
wdeAlreadyExistingItems[ propertyId ] = duplicates;
if ( propertyId === 'P166' && values.length === claims.length )
return;
}
if ( claims.length > 0 ) {
if ( claims[ 0 ].mainsnak.property === 'P19' || claims[ 0 ].mainsnak.property === 'P20' )
return;
}
callbackIfCan( true );
}
} );
}
// По умолчанию, если есть claims, то экспортировать нельзя
};
/**
* Генерация ID утверждения
*/
var wdeClaimGuid = function ( entityId ) {
var getRandomHex = function ( min, max ) {
return ( Math.floor( Math.random() * ( max - min + 1 ) ) + min ).toString( 16 );
};
var template = 'xx-x-x-x-xxx';
var guid = '';
for ( var i = 0; i < template.length; i++ ) {
if ( template.charAt( i ) === '-' ) {
guid += '-';
continue;
}
var hex;
if ( i === 3 ) {
hex = getRandomHex( 16384, 20479 );
} else if ( i === 4 ) {
hex = getRandomHex( 32768, 49151 );
} else {
hex = getRandomHex( 0, 65535 );
}
while ( hex.length < 4 ) {
hex = '0' + hex;
}
guid += hex;
}
return entityId + '$' + guid;
};
/**
* Форматирование дат в datavalue для викиданных
*/
var wdeCreateTimeSnak = function ( timestamp, forceJulian ) {
if ( !timestamp ) {
return;
}
var months = ['հունվար', 'փետրվար', 'մարտ', 'ապրիլ', 'մայիս', 'հունիս',
'հուլիս', 'օգոստոս', 'սեպտեմբեր', 'հոկտեմբեր', 'նոյեմբեր', 'դեկտեմբեր'];
var monthsGen = ['հունվարի', 'փետրվարի', 'մարտի', 'ապրիլի', 'մայիսի', 'հունիսի',
'հուլիսի', 'օգոստոսի', 'սեպտեմբերի', 'հոկտեմբերի', 'նոյեմբերի', 'դեկտեմբերի'];
var result = { timezone: 0, before: 0, after: 0 };
var isoDate;
var dateParts;
if ( timestamp.match ( /\s\([^\)]*\)\s/ ) ) {
forceJulian = true;
}
timestamp = timestamp.replace( /\([^\)]*\)/, '' ).trim();
var isBCE = false;
var bceMatch = timestamp.match( new RegExp( wdeConfig.reBCE ) );
if ( bceMatch ) {
isBCE = true;
timestamp = timestamp.replace( bceMatch[ 0 ], '' ).trim();
} else {
var ceMatch = timestamp.match( new RegExp( wdeConfig.reCE ) );
if ( ceMatch ) {
timestamp = timestamp.replace( ceMatch[ 0 ], '' ).trim();
}
}
if ( dateParts = timestamp.match( /^([ivx]{1,5})\s*(века?|в\.)?$/i ) ) {
isoDate = new Date( 0 );
isoDate.setFullYear( centuries.indexOf( dateParts[ 1 ].toUpperCase() ) * 100 + 1 );
result.precision = 7;
} else if ( dateParts = timestamp.match( new RegExp( '^(' + months.join( '|' ) + ')\\s+([12]\\d{3})$' ) ) ) {
isoDate = new Date( Date.UTC( dateParts[ 2 ], months.indexOf( dateParts[ 1 ] ) ) );
result.precision = 10;
} else if ( dateParts = timestamp.match( new RegExp( '(\\d{1,2})\\s+(' + monthsGen.join( '|' ) + ')[,\\s]+([12]\\d{3})(?:\\sгод|\.?$)' ) ) ) {
isoDate = new Date( Date.UTC( dateParts[ 3 ], monthsGen.indexOf( dateParts[ 2 ] ), dateParts[ 1 ] ) );
result.precision = 11;
} else if ( dateParts = timestamp.match( /^(\d{1,2})\.(\d{1,2})\.(\d{2,4})$/ ) ) {
isoDate = new Date( Date.UTC( dateParts[ 3 ] < 100 ? 1900 + parseInt( dateParts[ 3 ] ) : dateParts[ 3 ], dateParts[ 2 ] - 1, dateParts[ 1 ] ) );
result.precision = 11;
} else if ( dateParts = timestamp.match( /^(\d{4})-(\d{1,2})-(\d{1,2})/ ) ) {
isoDate = new Date( Date.UTC( dateParts[ 1 ] < 100 ? 1900 + parseInt( dateParts[ 1 ] ) : dateParts[ 1 ], dateParts[ 2 ] - 1, dateParts[ 3 ] ) );
result.precision = 11;
} else if ( dateParts = timestamp.match( /(\d{3,4})-[ех]/ ) ) {
isoDate = new Date( Date.UTC( dateParts[ 1 ], 0 ) );
result.precision = 8;
} else if ( dateParts = timestamp.match( /(\d{3,4})/ ) ) {
isoDate = new Date( Date.UTC( dateParts[ 1 ], 0 ) );
result.precision = 9;
} else if ( timestamp.match( /^այժմ$/ ) ) {
return 'novalue';
} else if ( timestamp.match( /^(\?|անհայտ)$/ ) ) {
return 'somevalue';
} else {
return;
}
try {
isoDate.setUTCHours( 0 );
isoDate.setUTCMinutes( 0 );
isoDate.setUTCSeconds( 0 );
result.time = ( isBCE ? '-' : '+' ) + isoDate.toISOString().replace( /\.000Z/, 'Z' );
} catch ( e ) {
return;
}
if ( result.precision < 11 ) {
result.time = result.time.replace( /-\d\dT/, '-00T' );
}
if ( result.precision < 10 ) {
result.time = result.time.replace( /-\d\d-/, '-00-' );
}
result.calendarmodel = 'http://www.wikidata.org/entity/Q' +
( forceJulian || isoDate < new Date( Date.UTC( 1582, 9, 15 ) ) ? '1985786' : '1985727' );
return result;
};
/**
* Отображение ошибки
*/
var wdeErrorDialog = function ( title, message ) {
var errorDialog = new OO.ui.MessageDialog();
wdeWindowManager.addWindows( [ errorDialog ] );
wdeWindowManager.openWindow( errorDialog, {
title: title,
message: message
} );
};
/**
* Достаем url сноски
*/
var wdeGetReference = function ( $field ) {
var references = [];
var $notes = $field.find( 'sup.reference a' );
for ( var i = 0; i < $notes.length; i++ ) {
var $externalLinks = $( decodeURIComponent($notes[ i ].hash).replace( /[!"$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, '\\$&' ) + ' a[rel="nofollow"]' );
for ( var j = 0; j < $externalLinks.length; j++ ) {
var $externalLink = $( $externalLinks.get( j ) );
if ( !$externalLink.attr( 'href' ).match( /(wikipedia.org|webcitation.org|archive.is)/ ) ) {
var source = {
snaks: {
P854: [ {
property: 'P854',
datatype: 'url',
snaktype: 'value',
datavalue: {
type: 'string',
value: $externalLink.attr( 'href' ).replace( /^\/\//, 'https://' )
}
} ]
}
};
// P813
var $accessed = $externalLinks.parent().find( 'small:contains("Проверено")' );
if ( $accessed.length ) {
var accessDate = wdeCreateTimeSnak( $accessed.first().text() );
if ( accessDate ) {
source.snaks.P813 = [ {
property: 'P813',
datatype: 'time',
snaktype: 'value',
datavalue: {
type: 'time',
value: accessDate
}
} ];
}
}
// P1065 + P2960
var $archiveLinks = $externalLinks.filter( 'a:contains("Архивировано")' );
if ( $archiveLinks.length ) {
var $archiveLink = $archiveLinks.first();
source.snaks.P1065 = [ {
property: 'P1065',
datatype: 'url',
snaktype: 'value',
datavalue: {
type: 'string',
value: $archiveLink.attr( 'href' ).replace( /^\/\//, 'https://' )
}
} ];
var archiveDate = wdeCreateTimeSnak( $archiveLink.parent().text().replace( 'Архивировано', '' ).trim() );
if ( archiveDate ) {
source.snaks.P2960 = [ {
property: 'P2960',
datatype: 'time',
snaktype: 'value',
datavalue: {
type: 'time',
value: archiveDate
}
} ];
}
}
references.push( source );
break;
}
}
}
references.push( { snaks: wdeConfig.references } );
return references;
};
/**
* Отформатировать источники для показа
*/
var wdeFormatDomains = function ( references ) {
var $result = $( '<sup>' );
for ( var i = 0; i < references.length; i++ ) {
var p854 = references[ i ].snaks.P854;
if ( p854 ) {
var domain = p854[ 0 ].datavalue.value.replace( 'http://', '' ).replace( 'https://', '' ).replace( 'www.', '' );
if ( domain.indexOf( '/' ) > 0 ) {
domain = domain.substr( 0, domain.indexOf( '/' ) );
}
$result.append( $( '<a>' ).attr( 'href', p854[ 0 ].datavalue.value ).text( '[' + domain + ']' ) );
}
}
return $result;
};
/**
* Форматирование wikidata values для показа пользователю
*/
var wdeFormatDataValue = function ( datavalue ) {
var $label = $( '<span>' );
switch ( datavalue.type ) {
case 'time':
var bceMark = ( datavalue.value.time.charAt( 0 ) === '-' ? ' до н. э.' : '' );
if ( datavalue.value.precision === 7 ) {
$label.text( centuries[ Math.floor( (datavalue.value.time.substr( 1, 4 ) - 1) / 100 ) ] + ' век' + bceMark );
break;
}
var options = {};
if ( datavalue.value.precision > 7 ) {
options.year = 'numeric';
}
if ( datavalue.value.precision > 9 ) {
options.month = 'long';
}
if ( datavalue.value.precision > 10 ) {
options.day = 'numeric';
}
var parsedDate = new Date( Date.parse( datavalue.value.time.substring( 1 ).replace( /-00/g, '-01' ) ) );
$label.text( parsedDate.toLocaleString( 'ru-ru', options ) + ( datavalue.value.precision === 8 ? '-е' : '' ) + bceMark );
break;
case 'quantity':
$label.append( $( '<strong>' ).text( datavalue.value.amount ) );
if ( datavalue.value.bound ) {
$label.append( $( '<span>' ).text( ' ± ' + datavalue.value.bound ) );
}
if ( datavalue.value.unit !== '1' ) {
var unitId = datavalue.value.unit.substr( datavalue.value.unit.indexOf( 'Q' ) );
var name = ( ( wdeConfig.units[ unitId ] || {} ).label || {} ).value || unitId;
var description = ( ( wdeConfig.units[ unitId ] || {} ).description || {} ).value || 'Невозможно подгрузить описание';
$label.append( ' ' ).append( $( '<abbr>' ).attr( 'title', description ).text( name ) );
}
break;
case 'wikibase-entityid':
$label.append( $( '<strong>' ).text( datavalue.value.label ? datavalue.value.label : datavalue.value.id ) )
.append( datavalue.value.description ? ' — ' + datavalue.value.description : '' );
break;
}
for ( var propertyId in datavalue.qualifiers ) {
if ( !datavalue.qualifiers.hasOwnProperty( propertyId ) ) {
continue;
}
if ( propertyId === 'P1480' && datavalue.qualifiers[ propertyId ][ 0 ].datavalue.value.id === 'Q5727902' ) {
$label.prepend( $( '<abbr>' ).attr( 'title', 'обстоятельства источника = около' ).text( 'ок.' ), ' ' );
} else {
var formatted = wdeFormatDataValue( datavalue.qualifiers[ propertyId ][ 0 ].datavalue );
if ( formatted && $( '<span>' ).append( formatted ).text() ) {
$label.append( $( '<span>' ).text( ' (' ).append( formatted ).append( ')' ) );
}
}
}
return $label;
};
var wdeGetWikidataIds = function ( titles, callback ) {
var languages = titles.map( function ( item ) {
return item.language;
} );
languages = $.merge( languages, wdeConfig.languages );
languages = $.unique( languages );
var sites = titles.map( function ( item ) {
return item.project;
} );
wdApi.get( {
action: 'wbgetentities',
sites: sites,
languages: languages,
props: [ 'labels', 'descriptions', 'claims' ],
titles: titles.map( function ( item ) {
return item.label;
} )
} ).done( function ( data ) {
if ( data.success ) {
var valuesObj = {};
var value;
for ( var entityId in data.entities ) {
if ( !data.entities.hasOwnProperty( entityId ) || !entityId.match( /^Q/ ) ) {
continue;
}
var entity = data.entities[ entityId ];
var label = entity.labels.ru || entity.labels.en || entity.labels[ Object.keys( entity.labels )[ 0 ] ] || '';
var description = entity.descriptions.ru || entity.descriptions.en || entity.descriptions[ Object.keys( entity.descriptions )[ 0 ] ] || '';
if ( ( ( ( ( ( ( ( entity || {} ).claims || {} ).P31 || [] )[ 0 ] || {} ).mainsnak || {} ).datavalue || {} ).value || {} ).id === 'Q4167410' ) {
continue; //пропускаем неоднозначности
}
var subclassFound = false;
var subclassEntity = null;
for ( var candidateId in data.entities ) {
if ( !data.entities.hasOwnProperty( candidateId ) || !candidateId.match( /^Q/ ) || entityId === candidateId ) {
continue;
}
subclassFound = [ 'P17', 'P31', 'P131', 'P279', 'P361' ].find( function ( propertyId ) {
var values = ( ( ( data.entities[ candidateId ] || {} ).claims || {} )[ propertyId ] || [] );
return values.find( function ( statement ) {
var result = ( ( ( statement.mainsnak || {} ).datavalue || {} ).value || {} ).id === entityId;
if ( result ) {
subclassEntity = data.entities[ candidateId ];
}
return result;
} );
} );
if ( subclassFound ) {
break;
}
}
if ( subclassFound ) {
if ( subclassEntity ) {
var subclassLabel = subclassEntity.labels.ru || subclassEntity.labels.en || subclassEntity.labels[ Object.keys( subclassEntity.labels )[ 0 ] ];
mw.notify( '«' + label.value + '» նշանակությունը հեռացվել է. արդեն կա ավելի կոնկրետը՝ «' + subclassLabel.value + '»', {
type: 'warn',
tag: 'wikidataInfoboxExport-warn-precise'
} );
}
continue; //пропускаем записи для которых есть более точные
}
value = {
wd: {
type: 'wikibase-entityid',
value: {
id: entityId,
label: label ? label.value : label,
description: description ? description.value : description
}
}
};
if ( label ) {
var results = titles.filter( function ( item ) {
return item.label.toLowerCase() === label.value.toLowerCase();
} );
if ( results.length === 1 ) {
value.wd.qualifiers = results[ 0 ].qualifiers;
}
}
value.label = wdeFormatDataValue( value.wd );
delete value.wd.value.label;
delete value.wd.value.description;
valuesObj[ entityId ] = value;
}
callback( valuesObj );
};
} );
};
var wdeParseItems = function ( $content, $wrapper, callback ) {
var titles = [];
var wdeProcessWbGetItems = function ( valuesObj ) {
var values = $.map( valuesObj, function( value, index ) {
return [ value ];
} );
if ( values.length === 1 ) {
value = values.pop();
wdeAddQualifiers( $wrapper, value.wd, value.label, function( value ) {
callback( [ value ] );
} );
} else if ( callback ) {
callback( values );
}
};
var fixedValues = [
{ property: 'P21', regexp: /իգական/, item: 'Q6581072', label: 'իգական' },
{ property: 'P21', regexp: /արական/, item: 'Q6581097', label: 'արական' },
{ property: 'P552', regexp: /прав/, item: 'Q3039938', label: 'աջլիկ' },
{ property: 'P552', regexp: /лев/, item: 'Q789447', label: 'ձախլիկ' },
{ property: 'P423', regexp: /прав/, item: 'Q10927630', label: 'праворукий удар' },
{ property: 'P423', regexp: /лев/, item: 'Q10927615', label: 'леворукий удар' }
];
for ( var k = 0; k < fixedValues.length; k++ ) {
if ( $content.attr( 'data-wikidata-property-id' ) === fixedValues[ k ].property && $content.text().match( fixedValues[ k ].regexp ) ) {
var result = { success: true, entities: {} };
result.entities[ fixedValues[ k ].item ] = {
labels: { ru: { value: fixedValues[ k ].label } },
descriptions: {}
};
wdeProcessWbGetItems( result );
return;
}
}
var $links = $content.find( 'a[title][class!=image][class!=new]' );
var redirects = [];
if ( $links.length ) {
for ( var j = 0; j < $links.length; j++ ) {
var $link = $( $links[ j ] );
if ( $link.parents( '[data-wikidata-qualifier-id]' ).length ) {
continue;
}
var extractedUrl = decodeURIComponent( $link.attr( 'href' ) ).replace( /^.*\/wiki\//, '' );
if ( extractedUrl ) {
extractedUrl = extractedUrl.replace( /_/g, ' ' ).trim();
var value = {
label: extractedUrl.charAt( 0 ).toUpperCase() + extractedUrl.substr( 1, extractedUrl.length - 1 ),
language: wdeConfig.language,
project: wdeConfig.project,
qualifiers: {}
};
var match = $links[ j ].innerHTML.match( /(\d\d\d\d)\s*(?:год|г\.?)/ );
if ( !match ) {
match = $links[ j ].innerHTML.match( / — (\d\d\d\d)/ );
}
var extractedYear = match ? wdeCreateTimeSnak( match[ 1 ] ) : wdeCreateTimeSnak( ( $links[ j ].nextSibling || {} ).textContent );
if ( extractedYear ) {
value.qualifiers.P585 = [ {
property: 'P585',
datatype: 'time',
snaktype: 'value',
datavalue: {
type: 'time',
value: extractedYear
}
} ];
}
if ( $link.hasClass( 'extiw' ) ) {
var m = $links[ j ].getAttribute( 'href' ).match( /^https:\/\/([a-z\-]+)\.(wik[^\.]+)\./ );
if ( m && m[ 2 ] !== 'wikimedia' ) {
value.language = m[ 1 ];
value.project = m[ 1 ] + m[ 2 ].replace( 'wikipedia', 'wiki' );
}
}
if ( $link.hasClass( 'mw-redirect' ) ) {
redirects.push( extractedUrl );
}
titles.push( value );
if ( $( $links[ j ] ).find( 'img' ) ) {
redirects.push( extractedUrl );
}
}
}
} else if ( $content.text().trim() ) {
// Если ссылок не нашлось, то пробуем искать статью по тексту
var parts = $content.text().split( /[\n,;]+/ );
for ( var i in parts ) {
var year = '';
var articleTitle = parts[ i ].replace( /\([^)]*\)/, function ( match ) {
year = match.replace( /\(\)/, '' );
return '';
} ).trim();
if ( articleTitle ) {
var value = {
label: articleTitle.charAt( 0 ).toUpperCase() + articleTitle.substr( 1, articleTitle.length - 1 ),
language: wdeConfig.language,
project: wdeConfig.project,
qualifiers: {}
};
if ( wdeCreateTimeSnak( year ) ) {
value.qualifiers.P585 = [ {
property: 'P585',
datatype: 'time',
snaktype: 'value',
datavalue: {
type: 'time',
value: wdeCreateTimeSnak( year )
}
} ];
}
titles.push( value );
}
}
titles = $.unique( titles );
}
if ( redirects.length ) {
api.get( {
action: 'query',
redirects: 1,
titles: redirects
} ).done( function ( data ) {
if ( data.query && data.query.redirects ) {
for ( var i = 0; i < data.query.redirects.length; i++ ) {
for ( var j = 0; j < titles.length; j++ ) {
var lcTitle = titles[ j ].label.substr( 0, 1 ).toLowerCase() + titles[ j ].label.substr( 1 );
var lcRedirect = data.query.redirects[ i ].from.substr( 0, 1 ).toLowerCase() + data.query.redirects[ i ].from.substr( 1 );
if ( lcTitle === lcRedirect ) {
titles.splice( j + 1, 0, {
label: data.query.redirects[ i ].to,
language: wdeConfig.language,
project: wdeConfig.project,
year: titles[ j ].year
} );
j++;
}
}
}
}
wdeGetWikidataIds( titles, wdeProcessWbGetItems );
} );
} else {
wdeGetWikidataIds( titles, wdeProcessWbGetItems );
}
};
/**
* Распарсивание количества и (опционально) точности
*/
var wdeParseQuantity = function ( text, forceInteger ) {
var out = {
value: {},
};
text = text.replace( /,/g, '.' ).replace( /[−–—]/g, '-' ).trim();
// Sourcing circumstances (P1480) = circa (Q5727902)
var circaMatch = text.match( new RegExp( wdeConfig.reCirca ) );
if ( circaMatch ) {
out.qualifiers = {
P1480: [ {
property: 'P1480',
snaktype: 'value',
datavalue: {
type: 'wikibase-entityid',
value: { id: 'Q5727902' }
}
} ],
};
text = text.replace( circaMatch[ 0 ], '' );
}
var magnitude = 0;
if ( text.match( /тыс/ ) ) {
magnitude += 3;
} else if ( text.match( /միլ|\dM(?:\s|$)|միլիոն|million/ ) ) {
magnitude += 6;
} else if ( text.match( /միլիարդ|մլրդ|billion/ ) ) {
magnitude += 9;
} else if ( text.match( /տրիլիարդ/ ) ) {
magnitude += 12;
} else {
var match = text.match( /[\*|·]10(-?\d+)/ );
if ( match ) {
text = text.replace( /[\*|·]10(-?\d+)/, '' );
magnitude += parseInt( match[ 1 ] );
}
}
var decimals = text.split( '±' );
if ( magnitude === 0 && forceInteger ) {
decimals[ 0 ] = decimals[ 0 ].replace( /\./g, '' ).trim();
}
var amount;
var bound;
var interval = decimals[ 0 ].split( '-' );
if ( magnitude === 0 &&
decimals.length === 1 &&
interval.length === 2 &&
interval[ 0 ].length !== 0 &&
interval[ 1 ].length !== 0
) {
out.value.lowerBound = interval[ 0 ].replace( /[^0-9.+-]/g, '' );
out.value.upperBound = interval[ 1 ].replace( /[^0-9.+-]/g, '' );
parts = out.value.lowerBound.match( /(\d+)\.(\d+)/ );
fractional = parts ? parts[ 2 ].length : 0;
out.value.amount = ( ( parseFloat( out.value.upperBound ) +
parseFloat( out.value.lowerBound ) )/2 )
.toFixed( fractional + 1 );
out.value.bound = ( ( parseFloat( out.value.upperBound ) -
parseFloat( out.value.lowerBound ) )/2 )
.toFixed( fractional + 1 );
return out;
} else {
amount = parseFloat( decimals[ 0 ].replace( /[^0-9.+-]/g, '' ) );
}
if ( isNaN( amount ) ) {
return;
}
var parts = amount.toString().match( /(\d+)\.(\d+)/ );
var integral = parts ? parts[ 1 ].length : amount.toString().length;
var fractional = parts ? parts[ 2 ].length : 0;
if ( magnitude >= 0 ) {
if ( magnitude <= fractional ) {
out.value.amount = ( ( '1e' + magnitude ) * amount ).toFixed( fractional - magnitude );
} else {
out.value.amount = ( ( '1e' + fractional ) * amount ).toFixed( 0 ).replace( /$/, new Array( magnitude - fractional + 1 ).join( '0' ) );
}
} else {
if ( magnitude >= -integral ) {
out.value.amount = ( ( '1e' + magnitude ) * amount ).toFixed( fractional - magnitude );
} else {
out.value.amount = ( ( '1e-' + integral ) * amount ).toFixed( integral + fractional ).replace( /0\./, '0.' + new Array( -magnitude - integral + 1 ).join( '0' ) );
}
}
if ( decimals.length > 1 ) {
bound = parseFloat( decimals[ 1 ].replace( /[^0-9.+-]/g, '' ) );
}
if ( !isNaN( bound ) ) {
if ( decimals.length > 1 && decimals[ 1 ].indexOf( '%' ) > 0 ) {
bound = amount * bound / 100;
} else {
parts = bound.toString().match( /(\d+)\.(\d+)/ );
integral = parts ? parts[ 1 ].length : amount.toString().length;
fractional = parts ? parts[ 2 ].length : 0;
}
if ( magnitude >= 0 ) {
if ( magnitude <= fractional ) {
out.value.lowerBound = ( ( '1e' + magnitude ) * ( amount - bound ) ).toFixed( fractional - magnitude );
out.value.upperBound = ( ( '1e' + magnitude ) * ( amount + bound ) ).toFixed( fractional - magnitude );
out.value.bound = ( ( '1e' + magnitude ) * bound ).toFixed( fractional - magnitude ); // нужно для показа пользователю
} else {
out.value.lowerBound = ( ( '1e' + fractional) * ( amount - bound ) ).toFixed( 0 ).replace( /$/, new Array( magnitude - fractional + 1 ).join( '0' ) );
out.value.upperBound = ( ( '1e' + fractional) * ( amount + bound ) ).toFixed( 0 ).replace( /$/, new Array( magnitude - fractional + 1 ).join( '0' ) );
out.value.bound = ( ( '1e' + fractional ) * bound ).toFixed( 0 ).replace( /$/, new Array( magnitude - fractional + 1 ).join( '0' ) );
}
} else {
if ( magnitude >= -integral ) {
out.value.lowerBound = ( ( '1e' + magnitude ) * ( amount - bound ) ).toFixed( fractional - magnitude );
out.value.upperBound = ( ( '1e' + magnitude ) * ( amount + bound ) ).toFixed( fractional - magnitude );
out.value.bound = ( ( '1e' + magnitude ) * bound ).toFixed( fractional - magnitude );
} else {
out.value.lowerBound = ( ( '1e-' + integral ) * ( amount - bound ) ).toFixed( integral + fractional ).replace( /0\./, '0.' + new Array( -magnitude - integral + 1 ).join( '0' ) );
out.value.upperBound = ( ( '1e-' + integral ) * ( amount + bound ) ).toFixed( integral + fractional ).replace( /0\./, '0.' + new Array( -magnitude - integral + 1 ).join( '0' ) );
out.value.bound = ( ( '1e-' + integral ) * bound ).toFixed( integral + fractional ).replace( /0\./, '0.' + new Array( -magnitude - integral + 1 ).join( '0' ) );
}
}
}
return out;
};
/**
* Распознавание единиц измерения в параметре карточки и его заголовке
*/
var wdeRecognizeUnits = function ( text, units, label ) {
if ( Array.isArray( units ) && units.length === 0 ) {
return [ '1' ];
}
var result = [];
for ( var idx in units ) {
if ( !units.hasOwnProperty( idx ) ) {
continue;
}
var item = parseInt( idx ) >= 0 ? units[ idx ] : idx;
var search = wdeConfig.units[ item ].search;
for ( var j = 0; j < search.length; j++ ) {
var expr = search[ j ];
if ( search[ j ].charAt( 0 ) !== '^' ) {
expr = '[\\d\\s\\.]' + expr;
if ( search[ j ].length < 5 ) {
expr = expr + '\\.?$';
}
}
if ( text.match( new RegExp( expr, 'i' ) ) ) {
result.push( item );
break;
} else if ( search[ j ].charAt( 0 ) !== '^' && label && label.match( new RegExp( '\\s' + search[ j ] + ':?$', 'i' ) ) ) {
result.push( item );
break;
}
}
}
return result;
};
/**
* Создание всех утверждений в Викиданных и отметка свойства экcпортированным
*/
var wdeCreateClaims = function ( propertyId, values, refUrl, revIds ) {
var value = values.shift();
revIds = revIds || [];
if ( !value ) {
// Все утверждения добавлены - переходим к установке меток
wdeAddTags( propertyId, revIds );
return;
} else {
value = JSON.parse( value );
}
var datatype = wdeConfig.properties[ propertyId ].datatype;
var mainsnak = value.value.toString().match( /^(novalue|somevalue)$/ ) ? {
snaktype: value.value,
property: propertyId
} : {
snaktype: 'value',
property: propertyId,
datavalue: {
type: wdeTypesMapping[ datatype ] ? wdeTypesMapping[ datatype ] : datatype,
value: value.value
}
};
var claim = {
type: 'statement',
mainsnak: mainsnak,
id: wdeClaimGuid( mw.config.get( 'wgWikibaseItemId' ) ),
references: refUrl,
rank: 'normal'
};
if ( value.qualifiers ) {
claim.qualifiers = value.qualifiers;
}
wdApi.postWithToken( 'csrf', {
action: 'wbsetclaim',
claim: JSON.stringify( claim ),
baserevid: wdeBaseRevId
} ).done( function ( claimData ) {
if ( claimData.success ) {
var valuesLeftStr = values.length ? ' (осталось ' + values.length + ')' : '';
mw.notify( 'Հասկացության նշանակությունը՝ ' + propertyId + ' հաջողությամբ ավելացվեց Վիքիտվյալների շտեմարանում' + valuesLeftStr, {
tag: 'wikidataInfoboxExport-success'
} );
wdeBaseRevId = claimData.pageinfo.lastrevid;
revIds.push( wdeBaseRevId );
wdeCreateClaims( propertyId, values, refUrl, revIds );
} else {
wdeErrorDialog( 'Ошибка при сохранении', JSON.stringify( claimData ) );
}
} );
};
/**
* Установка меток гаджета для сделанных правок
* FIXME: Добавлять метки сразу, когда будет исправлен [[phab:T155109]]
*/
var wdeAddTags = function ( propertyId, revIds ) {
wdApi.postWithToken( 'csrf', {
action: 'tag',
add: 'InfoboxExport gadget',
revid: revIds
} ).done( function ( data ) {
var success = false;
if ( data.tag ) {
success = true;
for ( var i = 0; i < data.tag.length; i++ ) {
if ( data.tag[ i ].status !== 'success' ) {
success = false;
break;
}
}
}
if ( success ) {
mw.notify( 'Метки правок в Викиданных успешно установлены', {
tag: 'wikidataInfoboxExport-tags-success'
} );
$( '.no-wikidata[data-wikidata-property-id=' + propertyId + ']' )
.removeClass( 'no-wikidata' )
.off( 'dblclick', wdeClickEvent );
} else {
mw.notify( 'Ошибка при установке метки правок в Викиданных', {
type: 'warn',
tag: 'wikidataInfoboxExport-tags-error'
} );
}
} );
};
/**
* Обёртка для предзагрузки информации о свойствах, исключающая уже загруженные.
*/
var wdeLoadProperties = function ( propertyIds ) {
if ( !propertyIds || !propertyIds.length ) {
return;
}
var realPropertyIds = [];
for ( var i in propertyIds ) {
var propertyId = propertyIds[ i ];
if ( propertyId && wdeConfig.properties[ propertyId ] === undefined ) {
realPropertyIds.push( propertyId );
}
}
if ( realPropertyIds.length ) {
wdeRealLoadProperties( realPropertyIds );
}
};
/**
* Предзагрузка информации о всех свойствах.
*/
var wdeRealLoadProperties = function ( propertyIds ) {
if ( !propertyIds || !propertyIds.length ) {
return;
}
var units = [];
wdApi.get( {
action: 'wbgetentities',
languages: wdeConfig.languages,
props: [ 'labels', 'datatype', 'claims' ],
ids: propertyIds
} ).done( function ( data ) {
if ( !data.success ) {
return;
}
for ( var propertyId in data.entities ) {
if ( !data.entities.hasOwnProperty( propertyId ) ) {
continue;
}
var entity = data.entities[ propertyId ];
var label = entity.labels[ wdeConfig.language ] ? entity.labels[ wdeConfig.language ].value : entity.labels.en.value;
wdeConfig.properties[ propertyId ] = {
datatype: entity.datatype,
label: label.charAt( 0 ).toUpperCase() + label.slice( 1 ),
constraints: { qualifier: [] },
units: []
};
if ( propertyId === 'P1128' || propertyId === 'P2196' ) {
wdeConfig.properties[ propertyId ].constraints.integer = 1;
}
if ( entity.claims ) {
// Ограничения свойства
if ( entity.claims.P2302 ) {
for ( var i in entity.claims.P2302 ) {
var type = ( ( ( ( entity.claims.P2302[ i ] || {} ).mainsnak || {} ).datavalue || {} ).value || {} ).id
switch ( type ) {
case 'Q19474404':
case 'Q21502410':
wdeConfig.properties[ propertyId ].constraints.unique = 1;
break;
case 'Q21510856': // "Обязательный" квалификатор
qualifiers = ( ( ( entity.claims.P2302[ i ] || {} ).qualifiers || {} ).P2306 || [] );
for ( var idx = 0; idx < qualifiers.length; idx++) {
var qualifierId = ( ( ( qualifiers[ idx ] || {}).datavalue || {} ).value || {} ).id;
if ( qualifierId ) {
wdeConfig.properties[ propertyId ].constraints.qualifier.push( qualifierId.toString() );
}
}
break;
case 'Q21514353': // Единицы измерения
qualifiers = ( ( ( entity.claims.P2302[ i ] || {} ).qualifiers || {} ).P2305 || [] );
for ( var idx = 0; idx < qualifiers.length; idx++) {
var unitId = ( ( ( qualifiers[ idx ] || {}).datavalue || {} ).value || {} ).id;
if ( unitId ) {
wdeConfig.properties[ propertyId ].units.push( unitId );
units.push( unitId );
}
}
break;
}
}
}
}
}
wdApi.get( {
action: 'wbgetentities',
languages: wdeConfig.languages,
props: [ 'labels', 'descriptions', 'aliases', 'claims' ],
ids: $.unique( units )
} ).done( function ( unitData ) {
if ( !unitData.success ) {
return;
}
for ( var unitId in unitData.entities ) {
var unit = unitData.entities[ unitId ];
var unitSearch = wdeConfig.units[ unitId ] ? wdeConfig.units[ unitId ].search : [];
if ( !wdeConfig.units[ unitId ] ) {
wdeConfig.units[ unitId ] = {};
}
// Метка
if ( unit.labels ) {
wdeConfig.units[ unitId ].label = unit.labels[ wdeConfig.language ] ||
unit.labels.en ||
unit.labels[ Object.keys( unit.labels )[ 0 ] ];
if ( unit.labels[ wdeConfig.language ] ) {
unitSearch.push( unit.labels[ wdeConfig.language ].value.replace( /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&' ) );
}
}
// Описание
if ( unit.descriptions ) {
wdeConfig.units[ unitId ].description = unit.descriptions[ wdeConfig.language ] ||
unit.descriptions.en ||
unit.descriptions[ Object.keys( unit.labels )[ 0 ] ];
}
// Алиасы
if ( unit.aliases && unit.aliases[ wdeConfig.language ] ) {
for ( var i in unit.aliases[ wdeConfig.language ] ) {
unitSearch.push( unit.aliases[ wdeConfig.language ][ i ].value.replace( /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&' ) );
}
}
// Обозначение единиц (P558)
if ( unit.claims && unit.claims.P558 ) {
for ( var i in unit.claims.P558 ) {
var claim = unit.claims.P558[ i ];
if ( claim.mainsnak &&
claim.mainsnak.datavalue &&
claim.mainsnak.datavalue.value
) {
unitSearch.push( claim.mainsnak.datavalue.value.replace( /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&' ) );
}
}
}
wdeConfig.units[ unitId ].search = unitSearch;
localStorage.setItem( 'wdeConfig', JSON.stringify( wdeConfig ) );
}
} );
} );
};
var wdeCheckForMisLang = function ( wd ) {
var lang = wd.value.language;
if ( 'misLang' in wdeConfig && lang in wdeConfig.misLang ) {
wd.value.language = 'mis';
if ( !( 'qualifiers' in wd ) ) {
wd.qualifiers = {};
}
wd.qualifiers.P585 = [ {
property: 'P2439',
snaktype: 'value',
datavalue: {
type: 'wikibase-entityid',
value: { id: wdeConfig.misLang[ lang ] }
}
} ];
}
return wd;
};
var wdeAddQualifiers = function ( $field, value, $label, callback ) {
var $qualifiers = $field.find( '[data-wikidata-qualifier-id]' );
if ( $qualifiers.length ) {
$label = $( '<div>' ).append( $label );
}
var addQualifierValue = function ( qualifierId, qualifierValue, qualifierLabel ) {
if ( value.qualifiers === undefined ) {
value.qualifiers = {};
}
if ( value.qualifiers[ qualifierId ] === undefined ) {
value.qualifiers[ qualifierId ] = [];
}
var datatype = wdeConfig.properties[ qualifierId ].datatype;
value.qualifiers[ qualifierId ].push( {
snaktype: 'value',
property: qualifierId,
datavalue: {
type: wdeTypesMapping[ datatype ] ? wdeTypesMapping[ datatype ] : datatype,
value: qualifierValue
}
} );
$label.append( $( '<p>' )
.append( $( '<a>' )
.attr( 'href', '//www.wikidata.org/wiki/Property:' + qualifierId )
.text( wdeConfig.properties[ qualifierId ].label )
)
.append( $( '<span>' ).text( ': ' ) )
.append( qualifierLabel )
);
};
var qualifierTitles = {};
for ( var q = 0; q < $qualifiers.length; q++ ) {
var $qualifier = $( $qualifiers[ q ] );
var qualifierId = $qualifier.data( 'wikidata-qualifier-id' );
var qualifierValue = $qualifier.text().replace( '\n', ' ' ).trim();
switch ( wdeConfig.properties[ qualifierId ].datatype ) {
case 'monolingualtext':
qualifierValue = {
text: $qualifier.text().replace( '\n', ' ' ).trim(),
language: $qualifier.attr( 'lang' ) || wdeConfig.language
};
addQualifierValue( qualifierId, qualifierValue, $qualifier.text() );
break;
case 'string':
qualifierValue = $qualifier.text().replace( '\n', ' ' ).trim();
addQualifierValue( qualifierId, qualifierValue, $qualifier.text() );
break;
case 'time':
qualifierValue = wdeCreateTimeSnak( qualifierValue );
addQualifierValue( qualifierId, qualifierValue, $qualifier.text() );
break;
case 'wikibase-item':
if ( qualifierTitles[ qualifierId ] === undefined ) {
qualifierTitles[ qualifierId ] = [];
}
var $links = $qualifier.find( 'a[title][class!=image][class!=new]' );
if ( $links.length ) {
for ( var l = 0; l < $links.length; l++ ) {
var $link = $( $links[ l ] );
var extractedUrl = decodeURIComponent( $link.attr( 'href' ) ).replace( /^.*\/wiki\//, '' );
if ( extractedUrl ) {
extractedUrl = extractedUrl.replace( /_/g, ' ' ).trim();
var title = {
label: extractedUrl.charAt( 0 ).toUpperCase() + extractedUrl.substr( 1, extractedUrl.length - 1 ),
language: wdeConfig.language,
project: wdeConfig.project,
qualifiers: {}
};
if ( $link.hasClass( 'extiw' ) ) {
var m = $link.attr( 'href' ).match( /^https:\/\/([a-z\-]+)\.(wik[^\.]+)\./ );
if ( m && m[ 2 ] !== 'wikimedia' ) {
title.language = m[ 1 ];
title.project = m[ 1 ] + m[ 2 ].replace( 'wikipedia', 'wiki' );
}
}
qualifierTitles[ qualifierId ].push( title );
}
}
} else {
qualifierTitles[ qualifierId ].push( {
label: qualifierValue.charAt( 0 ).toUpperCase() + qualifierValue.substr( 1, qualifierValue.length - 1 ),
language: wdeConfig.language,
project: wdeConfig.project,
qualifiers: {}
} );
}
break;
}
};
var processItemTitles = function ( itemTitles, callback ) {
if ( Object.keys( itemTitles ).length ) {
var qualifierId = Object.keys( itemTitles ).shift();
var qualifierItemTitles = itemTitles[ qualifierId ];
delete itemTitles[ qualifierId ];
wdeGetWikidataIds( qualifierItemTitles, function ( valuesObj ) {
for ( var entityId in valuesObj ) {
var valueObj = valuesObj[ entityId ];
addQualifierValue( qualifierId, valueObj.wd.value, valueObj.label );
}
processItemTitles( itemTitles, callback );
} );
} else {
callback( {
wd: value,
label: $label
} );
}
};
processItemTitles( qualifierTitles, callback );
};
/**
* Парсинг значений из параметров перед выводом диалога
*/
var wdePrepareDialog = function ( $field, propertyId ) {
var values = [];
var datatype = wdeConfig.properties[ propertyId ].datatype;
var $content = $field.clone();
$content.find( 'sup.reference' ).remove();
$content.find( '[style*="display:none"]' ).remove();
var $wrapper = $content;
var $row = $field.closest( 'tr' );
if ( $row.length === 1 && $row.find( '[data-wikidata-property-id]' ).length === 1 ) {
$wrapper = $row.clone();
}
switch ( datatype ) {
case 'commonsMedia':
var $imgs = $content.find( 'img' );
$imgs.each( function () {
var $img = $( this );
var src = $img.attr( 'src' );
if ( !src.match( /upload.wikimedia.org\/wikipedia\/commons/ ) ) {
return;
}
var srcParts = src.split( '/' );
var fileName = srcParts.pop();
if ( fileName.match( /(?:^|-)\d+px-/ ) ) {
fileName = srcParts.pop();
}
fileName = decodeURIComponent( fileName );
fileName = fileName.replace( /_/g, ' ' );
var value = { value: fileName };
var $label = $img.clone()
.attr( 'title', fileName )
.css( 'border', '1px dashed #a2a9b1' );
wdeAddQualifiers( $wrapper, value, $label, function( valueObj ) {
values.push( valueObj );
} );
} );
break;
case 'external-id':
var externalId = $content.data( 'wikidata-external-id' ) || $content.text();
if ( propertyId === 'P345' ) { // IMDB
externalId = $content.find( 'a' ).first().attr( 'href' );
externalId = externalId.substr( externalId.lastIndexOf( '/', externalId.length - 2 ) ).replace( /\//g, '' );
} else {
externalId = externalId.toString().replace( /^ID\s/, '' ).replace( /\s/g, '' );
}
var sparql = 'SELECT * WHERE { ?item wdt:' + propertyId + ' "' + externalId + '" }';
$.ajax( {
url: 'https://query.wikidata.org/sparql?format=json&query=' + sparql,
success: function ( data ) {
var $label = $( '<code>' ).text( externalId );
if ( data.results.bindings.length ) {
var url = data.results.bindings[ 0 ].item.value;
$label = $( '<span>' ).append( $( '<code>' ).text( externalId ) )
.append( $( '<strong>' ).css( { 'color': 'red' } ).text( ' уже используется в ' ) )
.append( $( '<a>' ).attr( 'href', url ).attr( 'target', '_blank' ).text( url.replace( /[^Q]*Q/, 'Q' ) ) );
}
wdeDialog( $field, propertyId, [ {
wd: { value: externalId.toString() },
label: $label
} ], wdeGetReference( $content ) );
}
} );
return;
case 'string':
var text = $content.data( 'wikidata-external-id' );
if ( !text ) {
text = $content.text();
}
var strings = text.toString().trim().split( /[\n,;]+/ );
// Commons category
if ( propertyId === 'P373' ) {
var $link = $content.find( 'a[class="extiw"]' ).first();
if ( $link.length ) {
var url = $link.attr( 'href' );
var value = url.substr( url.lastIndexOf( '/' ) + 1 )
.replace( /_/g, ' ' )
.replace( /^[Cc]ategory:/, '' )
.replace( /\?.*$/, '' );
value = decodeURIComponent( value );
strings = [ value ];
}
}
for ( var i in strings ) {
var s = strings[ i ].replace( /\n/g, ' ' ).trim();
if ( s ) {
values.push( {
wd: { value: s },
label: $( '<code>' + s + '</code>' )
} );
}
}
break;
case 'monolingualtext':
var $items = $content.find( 'span[lang]' );
$items.each( function () {
var $item = $( this );
values.push( {
wd: wdeCheckForMisLang( {
value: {
text: $item.text().trim(),
language: $item.attr( 'lang' ).trim()
}
} )
} );
} );
if ( !values.length ) {
var text = $content.text().trim();
if ( text ) {
var $items = mw.util.$content.find( 'span[lang]' );
$items.each( function () {
$item = $( this );
if ( $item.text().trim().startsWith( text ) ) {
values.push( {
wd: {
value: {
text: text,
language: $item.attr( 'lang' ).trim()
}
}
} );
}
} );
}
}
for ( var i in values ) {
values[ i ].label = $( '<span>' )
.append( $( '<span>' ).css( 'color', '#666' ).text( '(' + values[ i ].wd.value.language + ') ' ) )
.append( $( '<strong>' ).text( values[ i ].wd.value.text ) );
}
break;
case 'quantity':
var text = $content.text()
.replace( /[\u00a0\u25bc\u25b2]/g, ' ' )
.replace( /\s\(([^)]*\))/g, '' )
.trim();
// Хак для времени в формате hh:mm:ss и 00 мин. 00 сек.
var match = text.replace( /^(\d+)\s*м(?:ин)?\.?\s*(\d+)\s*с(?:ек)?\.?$/, '$1:$2' )
.match( /^(?:(\d+):)?(\d+):(\d+)$/ );
if ( match ) {
var amount = 0;
for ( var i = 1; i < match.length; i++ ) {
if ( match[ i ] !== undefined ) {
amount = amount * 60 + parseInt( match[ i ], 10 );
}
}
text = amount + ' сек.';
}
var result = { wd: wdeParseQuantity( text, wdeConfig.properties[ propertyId ].constraints.integer ) };
if ( !result.wd || !result.wd.value ) {
break;
}
wdeAddQualifiers( $wrapper, result.wd, wdeFormatDataValue( result.wd ), function( valueObj ) {
result = valueObj;
} );
if ( wdeConfig.properties[ propertyId ].constraints.qualifier.indexOf( 'P585' ) !== -1 ) {
var yearMatch = $content.text().match( /\(([^)]*[12]\s?\d\d\d)[,)\s]/ );
if ( !yearMatch ) {
yearMatch = $field.closest( 'tr' ).find( 'th' ).first().text().match( /\(([^)]*[12]\s?\d\d\d)[,)\s]/ );
}
if ( yearMatch ) {
if ( extractedDate = wdeCreateTimeSnak( yearMatch[ 1 ].replace ( /(\d)\s(\d)/, '$1$2' ) ) ) {
result.wd.qualifiers = {
P585: [ {
snaktype: 'value',
property: 'P585',
datavalue: {
type: 'time',
value: extractedDate
}
} ]
};
}
}
}
var qualMatch = $content.text().match( /\(([^\)]*)/ );
if ( qualMatch ) {
qualQuantity = wdeParseQuantity( qualMatch[ 1 ] );
if ( qualQuantity ) {
var supportedProperties = [ 'P2076', 'P2077' ];
for ( var j = 0; j < supportedProperties.length; j++ ) {
var units = wdeRecognizeUnits( qualMatch[ 1 ], wdeConfig.properties[ supportedProperties[ j ] ].units );
if ( units.length === 1 ) {
qualQuantity.value.unit = 'http://www.wikidata.org/entity/' + units[ 0 ];
if ( !result.wd.qualifiers ) {
result.wd.qualifiers = {};
}
result.wd.qualifiers[ supportedProperties[ j ] ] = [ {
snaktype: 'value',
property: supportedProperties[ j ],
datavalue: {
type: 'quantity',
value: qualQuantity.value
}
} ];
}
}
}
}
var founded = wdeRecognizeUnits( text, wdeConfig.properties[ propertyId ].units, $field.closest( 'tr' ).find( 'th' ).first().text() );
for ( var u = 0; u < founded.length; u++ ) {
result.wd.value.unit = '1';
if ( founded[ u ] !== '1' ) {
result.wd.value.unit = 'http://www.wikidata.org/entity/' + founded[ u ];
var item = wdeConfig.units[ founded[ u ] ];
}
result.wd.type = 'quantity';
result.label = wdeFormatDataValue( result.wd );
values.push( result );
}
break;
case 'time':
var value = wdeCreateTimeSnak( $content.text().toLowerCase().trim().replace( /\s+(года?|г\.?)$/, '' ),
$content[ 0 ].outerHTML.includes( 'по юлианскому' ) );
if ( value ) {
if ( value.toString().match( /^(novalue|somevalue)$/ ) ) {
values.push( {
wd: { value: value },
label: $( '<span>' )
.append( $( '<span>' ).css( 'color', '#666' ).text( 'Значение ' ) )
.append( $( '<strong>' ).text( value.toString() === 'novalue' ? 'отсутствует' : 'неизвестно' ) )
} );
} else {
values.push( {
wd: { value: value },
label: $( '<span>' )
.append( $( '<strong>' ).append( wdeFormatDataValue( {
type: 'time',
value: value
} ) ) )
.append( $( '<span>' ).css( 'color', '#666' ).text( ' (' +
( value.calendarmodel.includes( '1985727' ) ? 'Григорианский' : 'Юлианский' ) + ') ' ) )
} );
}
}
break;
case 'wikibase-item':
value = wdeParseItems( $content, $wrapper, function ( values ) {
wdeDialog( $field, propertyId, values, wdeGetReference( $content ) );
} );
return;
case 'url':
var $links = $content.find( 'a' );
$links.each( function () {
var $link = $( this );
var url = $link.attr( 'href' ).replace( /^\/\//, 'https://' );
values.push( {
wd: { value: url },
label: $( '<code>' + url + '</code>' )
} );
} );
break;
default:
mw.notify( 'Неизвестный тип данных свойства: ' + datatype, {
type: 'error',
tag: 'wikidataInfoboxExport-error'
} );
console.log( datatype, $content ); // тут надо
}
values = $.unique( values );
wdeDialog( $field, propertyId, values, wdeGetReference( $field ) );
};
/**
* Событие двойного клика по полю карточки
*/
var wdeClickEvent = function ( e ) {
var $field = $( this );
var propertyId = $field.attr( 'data-wikidata-property-id' );
wdePrepareDialog( $field, propertyId );
};
/**
* Вывод диалога для подтверждения экспорта
*/
var wdeDialog = function ( $field, propertyId, values, refUrl ) {
var fieldset;
if ( !values || !values.length ) {
mw.notify( 'Չհաջողվեց որոշել հասկացության նշանակությունը', {
type: 'error',
tag: 'wikidataInfoboxExport-error'
} );
return;
}
// Создание диалога
function ProcessDialog( config ) {
ProcessDialog.super.call( this, config );
}
OO.inheritClass( ProcessDialog, OO.ui.ProcessDialog );
ProcessDialog.static.name = 'Տեղափոխել Վիքիտվյալների շտեմարան';
ProcessDialog.static.title = $( '<span>' )
.attr( 'title', 'Տարբերակ ' + wdeConfig.version )
.text( ProcessDialog.static.name );
ProcessDialog.static.actions = [
{ action: 'export', label: 'Տեղափոխել', flags: [ 'primary', 'progressive' ] },
{ label: 'Չեղարկել', flags: [ 'safe' ] }
];
ProcessDialog.prototype.initialize = function () {
ProcessDialog.super.prototype.initialize.apply( this, arguments );
this.content = new OO.ui.PanelLayout( { padded: true, expanded: false } );
fieldset = new OO.ui.FieldsetLayout();
var firstSelected = false;
for ( var i = 0; i < values.length; i++ ) {
var alreadyInWikidata = ( wdeAlreadyExistingItems[ propertyId ] || [] ).includes( ( ( values[ i ].wd || {} ).value || {} ).id );
var checkbox = new OO.ui.CheckboxInputWidget( {
value: JSON.stringify( values[ i ].wd ),
selected: alreadyInWikidata,
disabled: alreadyInWikidata
} );
if ( !checkbox.isDisabled() ) {
if ( !firstSelected || !wdeConfig.properties[ propertyId ].constraints.unique ) {
firstSelected = true;
checkbox.setSelected( true );
}
if ( values[ i ].label[ 0 ].innerText.match( /уже используется/ ) &&
wdeConfig.properties[ propertyId ].constraints.unique &&
wdeConfig.properties[ propertyId ].datatype === 'external-id' ) {
checkbox.setSelected( false );
}
}
if ( refUrl ) {
values[ i ].label.append( wdeFormatDomains( refUrl ) );
}
fieldset.addItems( [
new OO.ui.FieldLayout( checkbox, {
label: values[ i ].label,
align: 'inline'
} )
] );
}
this.content.$element
.append( $( '<p>' ).append( $( '<strong>' )
.append( $( '<a>' ).attr( 'href', 'https://wikidata.org/wiki/Property:' + propertyId ).attr( 'target', '_blank' ).text( wdeConfig.properties[ propertyId ].label ) )
.append( $( '<span>' ).text( ':' ) )
) )
.append( fieldset.$element )
.append( $( '<hr>' ).css( 'margin-top', '1.5em' ) )
.append( $( '<p>' ).text( 'Տեղեկաքարտի հասկացության նշանակությունը տեղափոխե՞լ Վիքիտվյալների շտեմարան' ) )
.append( $( '<p>' ).css( 'font-size', 'smaller' ).html( 'Սեղմելով «Տեղափոխել» կոճակին՝ դուք համաձայնում եք <a href="https://foundation.wikimedia.org/wiki/Terms_of_Use" class="extiw" title="wikimedia:Terms of Use">օգտագործման կանոնների հետ</a> և համաձայնում եք անշահախնդիր ձեր ներդրումը հրապարակել<a rel="nofollow" class="external text" href="https://creativecommons.org/publicdomain/zero/1.0/">Creative Commons CC0 License</a> պայմաններով:' ) );
this.$body.append( this.content.$element );
};
ProcessDialog.prototype.getActionProcess = function ( action ) {
var dialog = this;
if ( action === 'export' ) {
return new OO.ui.Process( function () {
var values = [];
var fields = fieldset.getItems();
for ( var i in fields ) {
var checkbox = fields[ i ].getField();
if ( checkbox.isSelected() && !checkbox.isDisabled() ) {
values.push( checkbox.getValue() );
}
}
wdeCreateClaims( propertyId, values, refUrl );
dialog.close( { action: action } );
}, this );
}
return ProcessDialog.super.prototype.getActionProcess.call( this, action );
};
var windowManager = new OO.ui.WindowManager();
$( 'body' ).append( windowManager.$element );
var processDialog = new ProcessDialog();
windowManager.addWindows( [ processDialog ] );
windowManager.openWindow( processDialog );
};
/**
* Инициализация гаджета
*/
var wdeInit = function () {
if ( mw.config.get( 'wgWikibaseItemId' ) === null ||
mw.config.get( 'wgAction' ) !== 'view' ||
mw.util.getParamValue( 'veaction' ) !== null ||
( window.ve && window.ve.init ) ||
mw.config.get( 'wgNamespaceNumber' )
) {
return;
}
// Загрузка конфига из localStorage
var storedConfig;
try {
storedConfig = JSON.parse( localStorage.getItem( 'wdeConfig' ) );
} catch ( e ) {}
if ( storedConfig && storedConfig.version == wdeConfig.version ) {
wdeConfig = storedConfig;
}
if ( wdeConfig.properties === undefined ) {
wdeConfig.properties = {};
}
// Установка сайта и языка пользователя
wdeConfig.project = mw.config.get( 'wgDBname' );
wdeConfig.language = mw.user.options.get( 'language' ) || mw.config.get( 'wgContentLanguage' );
wdeConfig.languages.unshift( wdeConfig.language );
wdeConfig.languages = $.unique( wdeConfig.languages );
localStorage.setItem( 'wdeConfig', JSON.stringify( wdeConfig ) );
// Добавление ссылки на текущую страницу в источник
wdeConfig.references.P4656 = [ {
property: 'P4656',
datatype: 'url',
snaktype: 'value',
datavalue: {
type: 'string',
value: 'https://' + location.host + '/?oldid=' + mw.config.get( 'wgRevisionId' )
}
} ];
// Инициализация API
api = new mw.Api();
wdApi = new mw.ForeignApi( '//www.wikidata.org/w/api.php' );
// Инициализация диалогов
wdeWindowManager = new OO.ui.WindowManager();
$( 'body' ).append( wdeWindowManager.$element );
// Запрос данных элемента
wdApi.get( {
action: 'wbgetentities',
props: [ 'info', 'claims' ],
ids: mw.config.get( 'wgWikibaseItemId' )
} ).done( function ( data ) {
if ( data.success ) {
var claims;
for ( var i in data.entities ) {
if ( i == -1 ) {
return;
}
claims = data.entities[ i ].claims;
wdeBaseRevId = data.entities[ i ].lastrevid;
break;
}
if ( !claims ) {
return;
}
var $fields = $( '.infobox .no-wikidata' );
$fields.each( function () {
var $field = $( this );
var propertyId = $field.attr( 'data-wikidata-property-id' );
$field
.removeClass( 'no-wikidata' )
.off( 'dblclick' );
wdePropertyIds.push( propertyId );
wdeCanExportValue( $field, claims[ propertyId ], function ( hasClaims ) {
$field.addClass( 'no-wikidata' );
if ( hasClaims === true ) {
$field.addClass( 'partial-wikidata' );
}
$field.on( 'dblclick', wdeClickEvent );
} );
var $fieldQualifiers = $field.closest( 'tr' ).find( '[data-wikidata-qualifier-id]' );
$fieldQualifiers.each( function () {
wdePropertyIds.push( $( this ).data( 'wikidata-qualifier-id' ) );
} );
} );
mw.util.addCSS( '\
.infobox .no-wikidata {\
display: block !important;\
background: #fdc;\
padding: 5px 0;\
}\
.infobox .no-wikidata.partial-wikidata {\
background: #eeb;\
}\
.infobox .no-wikidata .no-wikidata {\
margin: -5px 0;\
}\
' );
// TODO: Загружать при первом открытии окна
wdeLoadProperties( wdePropertyIds );
}
} );
};
$.when(
$.ready,
mw.loader.using( [
'mediawiki.api',
'mediawiki.ForeignApi',
'mediawiki.util',
'oojs-ui-core',
'oojs-ui-widgets',
'oojs-ui-windows'
] )
).done( wdeInit );
}( mediaWiki, jQuery ) );