MediaWiki:Gadget-wikilinker.js: различия между версиями

Материал из Буквицы
Перейти к навигации Перейти к поиску
м (откат -отказ от registerTool)
мНет описания правки
Строка 3: Строка 3:




// Toolbar buttons
if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
 
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', WikiLinker );
};
 
var addNewToolbarButton = function() {
$( '#wpTextbox1' ).wikiEditor( 'addToToolbar', {
'section': 'main',
'group': 'format',
'tools': {
'wikilinker': {
label: 'Вики-ссыльщик — подбирает вики-ссылку для выделенного слова или словосочетания',
type: 'button',
icon: '//upload.wikimedia.org/wikipedia/commons/b/bd/Wikilinker.png',
action: {
type: 'callback',
execute: function() {
WikiLinker();
}
}
}
}
} );
};
 
if ( $.inArray( mw.config.get( 'wgAction' ), [ 'edit', 'submit' ] ) !== -1 ) {
importScript( 'MediaWiki:Stemmer.js' );
importScript( 'MediaWiki:Stemmer.js' );
mw.loader.using( [ 'user.options', 'jquery.textSelection' ], function () {
if ( mw.user.options.get( 'usebetatoolbar' ) === 1 ) {
$.when(
mw.loader.using( 'ext.wikiEditor' ),
$.ready
).then( addNewToolbarButton );
} else {
mw.loader.using( 'mediawiki.toolbar', function() {
$( addOldToolbarButton );
} );
}
} );
}
}


Строка 246: Строка 197:
}
}
};
};
if (typeof registerTool !== 'undefined') {
registerTool( {
name: 'wikilinker',
position: 300,
title: 'Викиссыльщик',
label: 'Викиссыльщик — подбирает вики-ссылку для выделенного слова или словосочетания',
callback: WikiLinker,
classic: {
icon: '//upload.wikimedia.org/wikipedia/commons/b/bd/Wikilinker.png',
},
visual: {
icon: '//upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Wikilinker_VE_icon.svg/20px-Wikilinker_VE_icon.svg.png',
modes: [ 'source' ],
addCallback: function () {
importScript( 'MediaWiki:Stemmer.js' );
},
},
} );
}

Версия от 16:45, 3 ноября 2021

// Russian Wiki Linker
// Find link for selected text


if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
	importScript( 'MediaWiki:Stemmer.js' );
}


function stemPhrase ( phrase ) {
	phrase = phrase
		.substr( 0, 100 )
		.replace( /[«»%'"]/g, '' )
		.replace( /[\s\-–—_!?\.,:;]+/g, ' ' )
		.trim();

	var rustemmer = new RussianStemmer();
 
	var arr = phrase.split(' ');
	var res = '';
	var nextRes = '';
 
	var n = 0;
 
	for ( var i in arr ) {
		rustemmer.setCurrent(arr[i]);
		rustemmer.stem();
		nextRes = rustemmer.getCurrent();
		if ( nextRes.length > 0 ) {
			if ( nextRes !== arr[i] && n < 3 ) {
				res += 'intitle:' + nextRes + '* ';
				n++; // в строке запроса может быть не более 3 звёздочек
			}
			else {
				res += nextRes + ' ';
			}
		}
	}
 
	// trim string
	res = res.replace( /(^\s+)|(\s+$)/g, '' );
 
	return res;
}


window.WikiLinker = function () {
 
	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 
		} );
	}

	processText( txt );


	function processText ( txt ) {
		var preparedText = stemPhrase( txt );
		// Использовать режим совместимости (поведение старого движка Lucene)
		preparedText = preparedText;
 		requestTokens = preparedText.split( ' ' ).length;
 		var url = mw.config.get( 'wgServer' ) + mw.config.get( 'wgScriptPath' ) + 
 			'/api.php?action=query&list=search&continue=' + 
 			'&srlimit=5&srprop=&format=json&srsearch=' + preparedText;

		loadXMLDoc( url );
	}
 

	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 compareStringLengths ( a, b ) {
		a = a.replace( / \(.*\)/g, '' );
		b = b.replace( / \(.*\)/g, '' );
 
		if ( a.length < b.length ) {
			return -1;
		}
		if ( a.length > b.length ) {
			return 1;
		}
		return 0;
	}
 

	function initialLower ( str ) {
		return str.substr( 0, 1 ).toLowerCase() + str.substr( 1 );
	}
 

	function stateChanged() {
		if ( xmlhttp.readyState === 4 ) {
			if ( xmlhttp.status === 200 ) {
				var resp = eval( '(' + xmlhttp.responseText + ')' );
 
				if ( typeof resp.query.search[0] !== 'undefined' ) {
 
					var pageName = resp.query.search[0].title;
 
					// если в запросе было только одно слово, то выбираем самое короткое название из первых трёх результатов
					// чтобы для "Аглией" выдавалось "Англия", а не "Англиканство"
 
					if ( requestTokens === 1 ) {
						var resar = [];
 
						for ( var j = 0; j <= 4; j++ ) {
							if ( typeof resp.query.search[j] !== 'undefined' &&
								txt.substr( 0, 3 ).toLowerCase() === resp.query.search[j].title.substr( 0, 3 ).toLowerCase()
							) {
								resar.push( resp.query.search[j].title );
							}
						}
 
						resar.sort( compareStringLengths );
 
						if ( typeof resar[0] !== 'undefined' ) {
							pageName = resar[0];
						}
					}
 
					// для "форумы" будет "[[форум]]ы", а не "[[форум|форумы]]"
					if ( initialLower( txt.substr( 0, pageName.length ) ) === initialLower( pageName ) &&
						pageName.length <= txt.length
					) {
						txt = '[[' + txt.substr( 0, pageName.length ) + ']]' +
							txt.substr( pageName.length, txt.length - pageName.length );
					}
					else {
						txt = '[[' + pageName + '|' + txt + ']]'; 
					}
				}
				else {
					txt = '[[' + '|' + txt + ']]';
				}

				$( '#wpTextbox1' )
					.textSelection( 'encapsulateSelection', {
						peri: txt,
						replace: true
					} )
					.textSelection( 'scrollToCaretPosition' )
			 		.focus();
			}
		}
	}
};

if (typeof registerTool !== 'undefined') {
	registerTool( {
	name: 'wikilinker',
	position: 300,
	title: 'Викиссыльщик',
	label: 'Викиссыльщик — подбирает вики-ссылку для выделенного слова или словосочетания',
	callback: WikiLinker,
	classic: {
		icon: '//upload.wikimedia.org/wikipedia/commons/b/bd/Wikilinker.png',
	},
	visual: {
		icon: '//upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Wikilinker_VE_icon.svg/20px-Wikilinker_VE_icon.svg.png',
		modes: [ 'source' ],
		addCallback: function () {
			importScript( 'MediaWiki:Stemmer.js' );
		},
	},
} );
}