/*
* В данный момент хорошо работает (проверял) подбор отдельного существительного, пары прил+сущ, предл+прил+сущ.
* Из замеченных недоработок - не определяет обратный порядок сущ+прил, а также составные названия из сущ-х (пример: князь Владимир)
*/
var url = '//astafiev.me/WikiLinker/links/';
// Toolbar buttons
var addOldToolbarButton = function() {
var $toolbar = $( '#gadget-toolbar' );
if ( !$toolbar.length ) {
$toolbar = $( '#toolbar' );
}
$( '<div>' )
.addClass( 'mw-toolbar-editbutton' )
.attr( 'id', 'mw-editbutton-gadget-wikilinker' )
.attr( 'alt', 'МорфоСсыльщик' )
.attr( 'title', 'МорфоСсыльщик — подбирает вики-ссылку для выделенного слова или словосочетания, учитывая словоизменение' )
.css( 'background-image', 'url(//upload.wikimedia.org/wikipedia/commons/a/ad/Wikilinker_toolbar.png) ' )
.appendTo( $toolbar )
.on( 'click', main );
};
var addNewToolbarButton = function() {
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
'section': 'main',
'group': 'format',
'tools': {
'morphlinker': {
label: 'МорфоСсыльщик — подбирает вики-ссылку для выделенного слова или словосочетания, учитывая словоизменение',
type: 'button',
icon: '//upload.wikimedia.org/wikipedia/commons/thumb/8/89/Glagoljica_Az.svg/13px-Glagoljica_Az.svg.png',
action: {
type: 'callback',
execute: function() {
main();
}
}
}
}
} );
};
if ( $.inArray( mw.config.get( 'wgAction' ), [ 'edit', 'submit' ] ) !== -1 ) {
mw.loader.using( [ 'user.options', 'jquery.textSelection' ], function () {
if ( mw.user.options.get( 'usebetatoolbar' ) === 1 ) {
if ( mw.user.options.get( 'showtoolbar' ) === 1 ) {
$.when(
mw.loader.using( ['ext.wikiEditor', 'schema.Edit'] ),
$.ready
).then( addNewToolbarButton );
}
} else {
mw.loader.using( 'mediawiki.toolbar', function() {
$( addOldToolbarButton );
} );
}
} );
}
function main(){
var xmlhttp;
var CantWork = 'Сначала нужно выделить слово или словосочетание';
var requestTokens = 0;
var $wpTextbox1 = $( '#wpTextbox1' );
var txt = $wpTextbox1.textSelection( 'getSelection' );
var startEndPos = $( '#wpTextbox1' ).textSelection( 'getCaretPosition', {
startAndEnd: true
} ),
startPos = startEndPos[0],
endPos = startEndPos[1];
// Trim selected text
while ( txt.slice( 0, 1 ) === ' ' ) {
txt = txt.slice( 1 );
startPos = startPos + 1;
}
while ( txt.slice( -1 ) === ' ' ) {
txt = txt.slice( 0, -1 );
endPos = endPos - 1;
}
if ( txt === '' ) {
mw.notify( CantWork );
return;
}
if ( startEndPos[0] !== startPos || startEndPos[1] !== endPos ) {
$wpTextbox1.textSelection( 'setSelection', {
start: startPos,
end: endPos
} );
}
loadXMLDoc( url + txt );
}
function loadXMLDoc ( url ) {
xmlhttp = GetXmlHttpObject();
if ( xmlhttp === null ) {
mw.notify( 'Your browser does not support XMLHTTP!' );
return;
}
xmlhttp.onreadystatechange = stateChanged;
xmlhttp.open( 'GET', url, true );
xmlhttp.send( null );
}
function GetXmlHttpObject() {
if ( window.XMLHttpRequest ) {
// code for IE7+, Firefox, Chrome, Opera, Safari
return new XMLHttpRequest();
}
if ( window.ActiveXObject ) {
// code for IE6, IE5
return new ActiveXObject( 'Microsoft.XMLHTTP' );
}
return null;
}
function stateChanged() {
if ( xmlhttp.readyState === 4 ) {
if ( xmlhttp.status === 200 ) {
var resp = JSON.parse( xmlhttp.responseText );
var список = [];
var морфол = "";
for (i=0; i<resp.части.length; i++){
var часть = resp.части[i];
var найденноеСлово;
var норма = false;
var noun = false, adj = false;
var узел = { исход: часть.слово, норма:null };
for (j=0; j<часть.варианты.length; j++){
var вариант = часть.варианты[j];
var noun_cand = вариант.частьРечи == 'существительное';
if (!noun && noun_cand){
noun = true;
найденноеСлово = вариант.базоваяФорма;
}
var adj_cand = вариант.частьРечи == 'прилагательное';
if (!noun && !adj && adj_cand){
adj = true;
найденноеСлово = вариант.базоваяФорма;
}
var норма_cand = false;
for (k=0; k<вариант.граммемы.length; k++){
if (вариант.граммемы[k] == 'именительный'){
норма_cand = true;
break;
}
}
if (норма_cand && (noun_cand||adj_cand) ){
noun = noun || noun_cand;
adj = adj || adj_cand;
норма = true;
найденноеСлово = вариант.базоваяФорма;
узел.формы = унифФормы(вариант.формы);
break;
}
}
// сохраняем слово в исходном виде, если не прил или сущ
if (!noun && !adj){
найденноеСлово = часть.слово;
морфол += "`";
} else {
морфол += noun? "с" : "п";
}
узел.норма = найденноеСлово;
список.push(узел);
}
// постобработка полученных норм
список = синтаксОбработка(морфол, список);
if (список.length < 1){
return;
}
var подстановка;
if (список.length > 1){
var ориг = список[0].слово.исход;
var нормФ = список[0].форма;
for (i=1; i<список.length; i++){
ориг = ориг + ' ' + список[i].слово.исход;
нормФ = нормФ + ' ' + список[i].форма;
}
подстановка = '[[' + нормФ + '|' + ориг + ']]';
} else {
var ориг = список[0].слово.исход;
var нормФ = список[0].форма;
if (нормФ.length <= ориг.length && ориг.substr(0, нормФ.length) == нормФ ){
подстановка = "[[" + нормФ + "]]" + ориг.substr(нормФ.length);
} else {
подстановка = "[[" + нормФ + "|" + ориг + "]]";
}
}
захватРезультата(подстановка);
}
}
}
function унифФормы(формы){
var карта = {};
формы.forEach ( function(форма) {
карта[форма.граммема] = форма.форма;
});
return карта;
}
function синтаксОбработка(морфология, слова){
// постобработка полученных норм
var синтСписок = [];
// var patt = /^((?:\:?пс)|(?:\:?п?с\:с))+$/;
// var patt = /((?:\:?пс)|(?:\:?п?с\:с))(?=(?:\:?пс)|(?:\:?п?с\:с)|$)/g;
var оснШаблон = /(?:^с)|(?:`?[уп]+с)|(?:`?п*с`с)/.source;
var шаблон = new RegExp( '('+оснШаблон+')(?='+оснШаблон+'|$)', 'g' );
while ( (res=шаблон.exec(морфология)) !== null ){
var фраза = res[1];
var начало = res.index;
if (фраза[0]=='`'){
var словоФорма = {слово:слова[начало], форма: слова[начало].исход };
синтСписок.push(словоФорма);
фраза = фраза.substr(1);
начало++;
}
var позСущ = фраза.indexOf('с');
if(фраза.length>1 && фраза[0]=='п' && 0 < позСущ && позСущ < фраза.search(/[`у]|$/) ){
var сущ = слова[позСущ];
var фс = сущ.формы;
// перебор определений
for (var i=начало; i<позСущ; i++){
var прил = слова[i];
var форма_прил = {слово: прил, форма: прил.норма };
{ // подбор рода/числа для слова-определения
var фп = прил.формы;
if (фс['множественное'] !== null && фп['множественное'] !== null){
форма_прил.форма = фп['множественное'];
}
delete фс.множественное;
for (var ключ in фс){
if (фп[ключ] !== null)
форма_прил.форма = фп[ключ];
}
}
синтСписок.push( форма_прил );
}
синтСписок.push( {слово: сущ, форма: сущ.норма } );
начало = позСущ+1;
}
if (фраза.length>0 && фраза[0]==='с' ){
синтСписок.push( {слово: слова[начало], форма: слова[начало].норма } );
начало++;
}
var форма = (начало<шаблон.lastIndex) && (фраза[начало]==='`');
for (и=начало; и<шаблон.lastIndex; и++){
var слово = слова[и];
синтСписок.push( {слово: слово, форма: форма? слово.исход : слово.норма } );
}
}
return синтСписок;
}
var захватРезультата = function (результат){
$( '#wpTextbox1' )
.textSelection( 'encapsulateSelection', {
peri: результат,
replace: true
} )
.textSelection( 'scrollToCaretPosition' )
.focus();
}