Участник:Andreyiv/dabfixer.js

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
if( $.inArray(mw.config.get('wgNamespaceNumber'), [0,2,10,14,100,102]) != -1 
    && /edit|submit/.test(mw.config.get('wgAction')) ) 
  addFuncBtn('dabfixer', dabFixer, 'commons/thumb/7/7f/Disambig_red.svg/20px-Disambig_red.svg.png', 'Разрешение неоднозначностей') 
 
 
 
function dabFixer(){
 
 
var disData = null, disIdx = -1, changes = [], dabMsgTimeout
var wikiText = $('#wpTextbox1').val()
var lnkRegExp, wikiLink, wikiLinkOrig, wikiLinkPos, snippetBefore, snippetAfter
 
//localization
//ruwiki
var $msg = 
{requesting:'Ждём ответа от тулсервера...'
,unlink_tip:'Заменить ссылку на текст'
,undo_tip:'Отменить сделанное исправление'
,choose_tip:'Уточните ссылку, кликнув на более точном значении ниже'
,x_tip:'отменить изменение'
,cancel:'отменить'
,cancel_tip:'отменить все сделанные изменения и закрыть диалог'
,next_tip:'перейти к следующей ссылке на неоднозначность'
,linksback:'есть <b>обратная ссылка</b>, вероятно исправления не нужно'
,nolinks:'В тексте не найдено ссылок на $1'
,cancelled:'Все изменения отменены'
,finished:'Исправлено ссылок:'
,nodablinks:'В статье не найдено ссылок на неоднозначности'
,summary:'разрешение [[ВП:Неоднозначность|неоднозначностей]]'
}
 
function $i(txt) { 
  return $msg[txt] || txt 
}
 
 
 
//send request
mw.util.addCSS('#dabMsg {background:#cec; border:1px solid; padding:0 10px}')
showMsg( $i('requesting'), 8000)
window.dabLinksProcess = dabLinksProcess
mw.loader.load('https://toolserver.org/~dispenser/cgi-bin/dablinks.py?\
format=json&callback=dabLinksProcess\
&titles='+mw.config.get('wgContentLanguage')+':'+encodeURIComponent(mw.config.get('wgPageName'))
+'&nocache='+Math.random())
return
 
 
 
 
//reseiving response
function dabLinksProcess(data){
 
 try { disData = data.query.pages[0].disambiguationlinks } catch(e){}
 if( !disData ) return showMsg( $i('nodablinks') )
 
 $('#mw-content-text').hide().parent().append('<div id=dabFrame>\
<pre id=dabText style="padding-left:2px;font-family:monospace, sans-serif" />\
<div id=dabTitle style="float:left; border:2px outset; border-bottom:none; padding:0 5px; margin-right:1em">\
 <span class=title />\
 <span class=choose style="cursor:help">↓&nbsp;</span></div>\
<div id=dabMenu>\
 <div style="float:right">\
  <span class=dabCount />\
  <button class=next>→</button>\
  <button class=cancel /></div>\
 <button class=unlink style="opacity:0.6"><s>[\[</s>&nbsp;<s>]]</s></button>\
 <button class=x/>\
 <span class=info>&nbsp;</span> <span class=linksback /></div>\
<div id=dabPage/>\
</div>')
 
 mw.util.addCSS('\
#dabFrame {padding:2px; border:1px solid gray}\
#dabFrame button {background:#cce; padding:0 5px; opacity:0.8; margin-left:0.5em;\
 font-size:85%; line-height:1.5em; vertical-align:top; cursor:pointer;}\
#dabText.text {word-wrap: break-word; white-space:pre-wrap; border:2px inset}\
#dabText .highlighted {background:#FFFF00}\
#dabText .changed {background:#A0E0A0}\
#dabPage {width:100%; border:2px outset; padding:10px 0;\
 max-height:230px; overflow-y:auto}\
#dabPage #disambig {font-size:75%; margin-bottom:0 !important; line-height:1em; padding:0}\
#dabPage span.editsection {display:none}\
#dabPage li.highlight {background-color:#F0F5F0; border:1px dotted gray}\
#dabPage a:hover {border-top:1px dotted green; border-top:1px dotted green}\
 ')
 
 $('#dabFrame button').click(buttonClicked)
 $('#dabPage').click(linkClicked)
 
 //automatically localize texts and tooltips using $msg
 $('#dabFrame span').add('#dabFrame button').each(function(){
  cl = this.className.split(' ')[0]
  if( !cl ) return
  $(this)
  .html( $msg[cl] || $(this).html() || cl )
  .attr( 'title', $msg[cl+'_tip'] || '' )
 })
 
 //start with 1st link
 $('#dabText')[0].scrollIntoView(true)
 nextLink()
 
}
 
 
 
function buttonClicked(){
 switch(this.className.split(' ')[0]){
 case 'next': 
   nextLink()
   break
 case 'cancel':
   showMsg( $i('cancelled') )
   finishDialog()
   break
 case 'unlink': 
   wikiLink = wikiLinkOrig.replace(/^\[\[|\]\]|.+\|/g,'')
   showArticleSnippet()
   break
 case 'x':
   wikiLink = wikiLinkOrig
   showArticleSnippet()
   break
 }
 return false
}
 
 
 
function showMsg(msg, time){
 if( dabMsgTimeout ) clearTimeout(dabMsgTimeout) 
 $('#dabMsg').remove()
 $('<div id=dabMsg />').append(msg).prependTo('#editform')[0].scrollIntoView()
 dabMsgTimeout = setTimeout( "$('#dabMsg').remove()", time||3000 )
}
 
 
function nextLink(){
 
 //save previous change
 if( wikiLink && (wikiLink != wikiLinkOrig) ){
   wikiText = wikiText.substring(0,wikiLinkPos) + wikiLink
    + wikiText.substr(wikiLinkPos+wikiLinkOrig.length)
   changes.push([wikiLinkOrig, wikiLink])
 }
 
 if( findDabInText() ) return showArticleSnippet() //show next link for the same dab title
 else if( ++disIdx < disData.length ) nextDabTitle() //switch to next dab title
 else finishDialog(true)
 
} 
 
 
 
function nextDabTitle(){ 
 
 var dab = disData[disIdx]
 
 //show dab title
 var ttl = dab.target || dab.title
 $('#dabTitle .title').html(
  '<a target=_blank href="'
   + mw.config.get('wgArticlePath').replace(/\$1/,'') + encodeURI(ttl).replace(/\?/g,'%3F')
   + '">' + ttl + '</a>'
 )  
 
 //update other areas 
 $('#dabPage').empty()
 $('#dabFrame .dabCount').text( (disIdx + 1) + '/' + disData.length)
 $('#dabMenu .linksback').toggle( dab.linksback==1 )
 
 //create regexp for dab title
 var i, ch, re = ''
 for( i=0; ch=dab.title.charAt(i), i<dab.title.length; i++ ) //escape special chars
    re += ('(){}^$.+*|/\\'.indexOf(ch) != -1 ? '\\' :'') + ch
 ch = re.charAt(0) // 'word' -> '(w|W)ord'
 if( /^[\wА-ЯЁ]/.test(ch) ) re = '('+ch+'|'+ch.toLowerCase()+')' + re.substring(1)
 lnkRegExp = new RegExp('\\[\\[\\s*'+re+'\\s*(\\|[^\\[\\]]+)?\\]\\][a-zа-яё]*', 'g')
 
 //see if we can find dab title in text
 if( findDabInText() ){
   showArticleSnippet()
   $('#dabPage').html('<img src=/skins-1.5/common/images/spinner.gif />')
    .load(mw.config.get('wgScript')+'?action=render&title='+encodeURIComponent(dab.title), guessDab)
 }else{
   $('#dabText').removeClass('text').html(
     '<i><center>' 
      + $i('nolinks').replace(/\$1/,'<b>[\['+dab.title+']]</b>') 
      + '</center></i>' )
 }
}
 
 
 
 
function findDabInText(){
 if( !lnkRegExp || !(wikiLink=lnkRegExp.exec(wikiText)) ) return false
 wikiLink = wikiLinkOrig = wikiLink[0]
 wikiLinkPos = lnkRegExp.lastIndex - wikiLink.length
 var p = wikiText.lastIndexOf('\n', wikiLinkPos-100)+1
 if (wikiLinkPos-p > 500) p = wikiText.lastIndexOf('. ', wikiLinkPos-150)+2
 if (wikiLinkPos-p > 500) p = wikiText.lastIndexOf(' ',  wikiLinkPos-200)+1
 if (wikiLinkPos-p > 500) p = wikiLinkPos-200
 snippetBefore = mw.html.escape(wikiText.substring(p,wikiLinkPos))
 p = wikiText.indexOf('\n', wikiLinkPos + 100)
 if (p-wikiLinkPos > 500) p = wikiText.indexOf('. ', wikiLinkPos+150)
 if (p-wikiLinkPos > 500) p = wikiText.indexOf(' ',  wikiLinkPos+200)
 if (p-wikiLinkPos > 500) p = wikiLinkPos+200
 snippetAfter = mw.html.escape(wikiText.substring(wikiLinkPos+wikiLink.length, p))
 return true
}
 
 
 
function showArticleSnippet(){
 var isChanged = wikiLink != wikiLinkOrig
 $('#dabText').empty().addClass('text').append(snippetBefore
  +'<span class=highlighted>'+mw.html.escape(wikiLink)+'</span>'+snippetAfter)
 $('#dabText .highlighted').toggleClass('changed', isChanged)
 $('#dabMenu button.x').css('visibility', isChanged?'visible':'hidden')
 $('#dabMenu button.unlink').css('visibility', /^\[/.test(wikiLink)?'visible':'hidden')
}
 
 
 
function finishDialog(isSuccess){
 if( isSuccess ){
   $('#wpTextbox1').val(wikiText)
   var sm = $('#wpSummary').val()
   if( sm.indexOf($i('summary')) == -1 )
     $('#wpSummary').val( sm + (sm?', ':'') + $i('summary') )
   showMsg( $i('finished') +  ' ' + changes.length )
 }
 $('#dabFrame').remove()
 $('#mw-content-text').show()
}
 
 
 
 
function linkClicked(e){
 e.preventDefault()
 if( e.target.nodeName != 'A' ) return
 var targ = $(e.target)
 // !!! todo: check for parent metadata 
 var ttl = targ.attr('href')
 ttl = targ.hasClass('new')  
       ? /\?title=([^&]+)/. exec( ttl ) 
       : /\/wiki\/([^\?]+)/.exec( ttl )
 if( !ttl ) return
 ttl = decodeURIComponent( ttl[1] ).replace( /_/g, ' ' )
 wikiLink = wikiLinkOrig.replace( /\[\[(.+\|)?(.+)\]\](.+)?/, 
   function(str, lnk, name, trail){
     return '[\[' + ttl + '|' + name + (trail||'') + ']]'
 })
 showArticleSnippet()
 return false
}
 
 
 
 
 
 
function guessDab(){ //try to guess wich link on dab page is closer to article being edited
 $('#floating_object').remove()
 var words, word, score, count, ma, lis = $('#dabPage li')
 for (var l=0; l<lis.length;l++){
   score = 0; count = 0
   words = lis.eq(l).text().replace(/[^\wа-яё]+/gi,' ').split(' ')
   for (var i=0; i<words.length; i++){
     word = words[i]
     if (/^[а-яё]+$/i.test(word)) word = word.substr(0, word.length-2) //rus suffix
     if (word.length < 4) continue //too short
	 if (disData[disIdx].title.match(RegExp('^'+word,'i'))) continue //disambig title 
	 count++
     ma = wikiText.match(RegExp(word, 'ig'))
	 if (!ma) continue
	 score += ma.length
   }
   lis[l].score = score / count
 }
 lis.sort(function(a,b){return b.score-a.score})
 lis.eq(0).addClass('highlight')
}

}