Участник:Lvova/monobook.js

Материал из Викисловаря

Замечание: Возможно, после публикации вам придётся очистить кэш своего браузера, чтобы увидеть изменения.

  • Firefox / Safari: Удерживая клавишу Shift, нажмите на панели инструментов Обновить либо нажмите Ctrl+F5 или Ctrl+R (⌘+R на Mac)
  • Google Chrome: Нажмите Ctrl+Shift+R (⌘+Shift+R на Mac)
  • Internet Explorer / Edge: Удерживая Ctrl, нажмите Обновить либо нажмите Ctrl+F5
  • Opera: Нажмите Ctrl+F5.
$(function(){addPortletLink('p-cactions', mw.config.get('wgServer')+mw.config.get('wgScript')+'?title='+encodeURIComponent(mw.config.get('wgPageName'))+'&action=purge', '', 'ca-purge', 'Очистить кеш сервера для этой страницы')})

function $(l) {return document.getElementById(l)}
 
$(function() {
  var pn = $('pt-userpage').parentNode
  if (!pn) return
 
  var bm = [
            "Special:Contributions/РобоСтася|робостася",
           ]
  var s = '<li>'
 
  for (var i in bm) {
    if (bm[i] == '-')
      s += '</li><li>'
    else {
      m = bm[i].match(/(.*)\|(.*)/)
      s += '<a title="' + m[1] + '" href="' + (/^https?:\/\//.test(bm[i]) ? m[1]:
            mw.config.get('wgServer') + mw.config.get('wgArticlePath').replace(/\$1$/, encodeURI(m[1])))
            + '">' + m[2] + '</a> '
    }
  }
  pn.innerHTML = s + '</li>' + pn.innerHTML
})

$(summaryPreview)

function summaryPreview(){

 var select, inputId, isEdit,  maxChars = 255, useMWPreview

 if (wgAction == 'edit' || wgAction == 'submit'){
   inputId = 'wpSummary'
   isEdit = true
   maxChars = 200
 }else if (wgCanonicalNamespace == 'Special' && wgCanonicalSpecialPageName == 'Movepage'){
   inputId = 'wpReason'
 }else if (wgAction == 'delete'){
   inputId = 'wpReason'
   select = document.getElementById('wpDeleteReasonList')
   addHandler(select, 'change', update)
 }else if (wgAction == 'protect'){
   inputId = 'mwProtect-reason'
 }else return

 var input = document.getElementById(inputId)
 if (!input) return

 //create counter span
 var cnt = document.createElement('span')
 cnt.id = 'inputCounter'
 cnt.style.marginLeft = '3px'
 input.parentNode.insertBefore(cnt, input.nextSibling)

 //create preview div
 var preview = document.createElement('div')
 preview.id = 'sumPreview'
 preview.title = 'Предварительный просмотр описания'
 with (preview.style){border = '1px solid gray'; width = '100%'; 
  fontStyle = 'italic'; fontSize='90%'; paddingLeft = '2px'}

 //add CSS
 var inputStyle = addCSS('#' + inputId
  + '{' + (window.oversizedSummaryCSS ? oversizedSummaryCSS : 'background:#FFEEEE') + '}')
 inputStyle.disabled = true

 //attach preview div
 if (isEdit){ 
   var el = document.getElementById('wpMinoredit')
   if (!el) return
   el.parentNode.insertBefore(preview, el)
   //hide standard preview
   el = preview
   while ((el=el.previousSibling) && (el.tagName != 'DIV'));
   if (el && el.className == 'mw-summary-preview'){
     var t = el.getElementsByTagName('span')[0].innerHTML
     preview.innerHTML = t.substring(1, t.length-1) //cut ()
     el.style.display = 'none'
     useMWPreview = true
   }else{
     preview.innerHTML = '&nbsp;'
   } 
 }else{
   input.form.appendChild(preview)
 }

 update()
 //assign events
 addHandler(input, 'change', update)
 addHandler(input, 'keyup', update)
 addHandler(input, 'mouseup', update)
 useMWPreview = false

 //functions

 function update(){
  var text = input.value, cutAt, bb
  if (select && (select.selectedIndex != 0)) text = select.value + ': ' + text
  var chars = text.length
  //count bytes
  bytes = 0
  for (var i=0; i<chars; i++){
    bytes++
    bb = text.charCodeAt(i)
    if (bb > 127) { 
      bytes++
      if (bb > 2048) bytes++
    }
    if (bytes > 255) cutAt = i
  }
  //show bytes/chars
  cnt.title = 'Used ' + chars + ' chars, ' + bytes + ' bytes'
  cnt.style.opacity = chars/maxChars
  var left
  if (255-bytes < maxChars-chars) { left = 255-bytes; cnt.style.fontStyle = 'italic' }
  else { left=maxChars-chars;  cnt.style.fontStyle = 'normal'}
  cnt.innerHTML = left
  cnt.style.fontColor = (left < 0) ? 'red' : 'black'
  cnt.style.fontWeight = (left < 20)? 'bold' : 'normal'
  inputStyle.disabled = (left >= 0) 
  //show preview
  if (useMWPreview) return
  if (bytes > 255) text = text.substring(0, cutAt)
  text = text.replace(/ +/g, ' ').replace(/</g,'&lt;') //collapse multiple spaces and make safe
  text = text.replace(/\/\*(.*?)\*\//g, 
    function(str, p){
     p = p.replace(/^ */,'').replace(/ *$/,'')
     return '<span class="autocomment">'
     + (isEdit ? '<a href="/wiki/'+wgPageName
       + '#' + encodeURI(p.replace(/ /g,'_')).replace(/%([0-9A-F][0-9A-F])/g, '.$1')
       + '" title="' +wgPageName.replace(/_/g, ' ') + '">→</a>' + p + ' -' : p )
     + '</span>'
   })
  
  text = text.replace(/\[\[([^\]><}{|]+)\|?([^\]><]*)?\]\]/g,
   function(str,p1,p2){ //[ [ p1 | p2 ] ]
    return '<a href='+wgServer+'/wiki/' 
    + encodeURI(p1.replace(/\?/g,'%3F').replace(/&/g,'%26'))
    +' + title=\'' + p1 + '\'>' + (p2?p2:p1) + '</a>'
   })
  preview.innerHTML = text ? text : '&nbsp;'
 }  


 function addCSS(text){ //could use createStyleSheet for IE as well
  var s = document.createElement('style')
  s.setAttribute('type', 'text/css')
  if (s.styleSheet) s.styleSheet.cssText = text //IE
  else s.appendChild(document.createTextNode(text))
  document.getElementsByTagName('head')[0].appendChild(s)
  return s.sheet || s //Safari needs sheets, IE the other way
 }

}

//var urlDecoderEngNames = true //set this to true to convert some keywords to English

if (typeof urlDecoderEngNames == 'boolean') 
urlDecoderEngNames = {
'User' : 'Участник',
'User_talk' : 'Обсуждение_участника',
'Special' : 'Служебная',
'Template': 'Шаблон',
'Template_talk': 'Обсуждение_шаблона',
'MediaWiki_talk': 'Обсуждение_MediaWiki'
} 

var urlDecoderTooltip = 'Раскодировать все URL в выделенном тексте или один URL перед курсором или '


if (wgAction=='edit' || wgAction=='submit') addOnloadHook(urlDecoderAddButton)


function urlDecoderAddButton() {
 addToolbarButton('%%', urlDecoderRun, 'btndecodeURL', 
    window.urlDecoderTooltip || 'Decode all URLS in selected text or one URL just before cursor or ')
 function addToolbarButton(name, onclick, id, tooltip, accesskey){
	var toolbar = document.getElementById('toolbar')
	if (!toolbar) return
	var newBtn = document.createElement('input')
	newBtn.type = 'button'; newBtn.style.cssText = 'background:#adbede; height:22px; vertical-align:top; padding:0'
	if (name) newBtn.value = name
	if (onclick) newBtn.onclick = onclick
	if (id) newBtn.id = id
	if (tooltip) newBtn.title = tooltip
	if (accesskey) newBtn.accessKey = accesskey
	toolbar.appendChild(newBtn)
	return newBtn
 }
}




function urlDecoderRun(){ //main function

var projPrefix = {
'test.wikipedia.org': 'testwiki',
'wikipedia.org':  'w',
'wikibooks.org':  'b',
'wikinews.org':   'n',
'wikiquote.org':  'q',
'wikisource.org': 's',
'wikiversity.org':'v', 
'wiktionary.org': 'wikt',
'mediawiki.org':'mw', 
'www.wikimedia.org': 'foundation',
'wikimedia.org': '*',
'wikimediafoundation.org': 'foundation'
} 

var httpBeforeCursor = /(\[{0,2})(https?:\/\/[^\]\n\r <>]+)$/i
var localPrefix = getPrefixes(wgServer.substring(7))
if (wgServer == 'https://secure.wikimedia.org')
  localPrefix = getPrefixes(wgScript.split('/')[2]+'.'+wgScript.split('/')[1]+'.org')
var selText, newText, matched, txtarea = document.editform.wpTextbox1

if (document.selection) { //IE/Opera
  var scrollTop = document.documentElement.scrollTop
  txtarea.focus()
  range = document.selection.createRange()
  if (!range.moveStart) return //some older browser?
  selText = range.text
  if (selText){
     newText = decodeLinks(selText)
  }else { //no selection, check if we're at the end of URL
    if (!range.duplicate) return
    rr = range.duplicate()
    rr.moveStart('character', - 500)
    matched = rr.text.match(httpBeforeCursor)
    if (!matched) return
    range.moveStart('character', - matched[0].length) //select matched
    selText = range.text
    newText = decodeLinkBeforeCursor(matched[1], matched[2])
  }
  //replace text if changed
  if (newText != selText){
    range.text = newText
    if (navigator.userAgent.indexOf('MSIE') != -1) newText = newText.replace(/\r/g,'') //for IE: do not count \r
    range.moveStart('character', - newText.length)
    range.select()
  }
  document.documentElement.scrollTop = scrollTop //restore window scroll position

}else if (txtarea.selectionStart || txtarea.selectionStart == '0') { // Mozilla
  var scrollTop = txtarea.scrollTop, txt = txtarea.value
  txtarea.focus()
  var startPos = txtarea.selectionStart, endPos = txtarea.selectionEnd
  if (startPos != endPos){
    selText = txt.substring(startPos, endPos)
    newText = decodeLinks(selText)
  }else{ //no selection, check if we're at the end of URL
    matched = txt.substring((endPos-600>0?endPos-600:0), endPos).match(httpBeforeCursor)
    if (!matched) return
    startPos = endPos - matched[0].length //select matched
    selText = matched[0]
    newText = decodeLinkBeforeCursor(matched[1], matched[2])
  }
  //replace text if changed
  if (newText != selText){
    txtarea.value = txt.substring(0, startPos) + newText +	txt.substring(endPos, txtarea.value.length)
    txtarea.selectionEnd = startPos + newText.length
    txtarea.selectionStart = startPos
  }
  txtarea.scrollTop = scrollTop
}



// *** Internal functions ***

//decode many links in selected text
function decodeLinks(txt){

 txt = txt.replace(/\[?\[(https?:\/\/[^\[\]]+)\]\]?/g, bracketedLink)
 txt = txt.replace(/(^|[^\[])(https?:\/\/[^\n\r ]+)/g, simpleLink) //unnamed link
 return txt

 function bracketedLink(str, url){
  var name = '', i = url.indexOf(' ')
  if (i != -1) { name = url.substring(i+1); url = url.substring(0,i) }
  str = decodeLink(url, name)
  if (str.charAt(0) != '[' ) str = '['+str+']' //not a wiki link, restore (single)  brackets
  return str
 }

 function simpleLink(str, charBefore, url){
   return charBefore + decodeNonameLink(url)
 }


}


//decode (leading bracket(s)) and one url
function decodeLinkBeforeCursor(brackets, url){ 
 var link = decodeNonameLink(url)
 if (link.charAt(0) != '[' && brackets) link = '[' + link //was not converted to wiki link: add just one bracket
 return link
}


//decode one link without name, make sure it does not end with dot
function decodeNonameLink(txt){
 var dot = ''
 if (txt.charAt(txt.length-1) == '.') { dot = '.'; txt = txt.substring(0, txt.length-1) }
 txt = decodeLink(txt)
 return txt + dot
}


function decodeLink(url, name){
 var parts
 //secure Wikimedia link into non-secure
 url = url.replace(/https:\/\/secure.wikimedia.org\/(\w+)\/(\w+)\/([^\]\|\n\r ]+)/,  'http://$2.$1.org/$3')
 //bugzilla
 if (parts = url.match(/^https:\/\/bugzilla\.wikimedia.org\/show_bug\.cgi\?id=(\d+)/))
    return '[\[mediazilla:'+parts[1]+']]'
 //decode %
 if (url.indexOf('%') != -1) try { url = decodeURI(url) } catch(e){}
 url = url.replace(/</g,'%3C').replace(/>/g,'%3E') //except angle brackets
 if (url.indexOf('%') != -1) //since we used decodeURI and not decodeURIComponent ...
    url = url.replace(/%3A/g,':').replace(/%3B/g, ';').replace(/%2F/g,'/').replace(/%2C/g,',')
 //no spaces
 url = url.replace(/ /g,'_')
 //convert to eng keywords
 for (var n in window.urlDecoderEngNames)
    url = url.replace(RegExp('(title=|wiki\/)('+urlDecoderEngNames[n]+':)'), '$1' + n + ':')
 //analyze
 parts = url.substring(7).split('/')
 var domain = parts[0]
 var linkPrefix = getPrefixes(domain)
 //return unchanged if cannot convert  into wiki link 
 if (!linkPrefix || parts[1] != 'wiki' || url.indexOf('?')!=-1)
    return name ?  '[' + url + ' ' + name + ']' : url
 //convert to wiki link
 var prefixes = ''
 var title = url.substring(parts[0].length + parts[1].length + 9) //get part after  /wiki/
 title = title.replace(/_/g, ' ')
 //prefixes
 if (linkPrefix[0] && (linkPrefix[0] != localPrefix[0])) prefixes += linkPrefix[0]
 if (linkPrefix[1] && (linkPrefix[1] != localPrefix[1])) prefixes += ':'+linkPrefix[1]
 //add extra : if needed  
 if (prefixes) prefixes += ':'
 else if (/^image:|\.(jpg|png|svg|gif)$|^category:|^категория:/i.test(title)) prefixes = ':'
 //decode anchor
 parts = title.split('#')
 if (parts.length == 2) try { 
   title = parts[0] + '#' + decodeURIComponent(parts[1].replace(/(\.)([0-9A-F][0-9A-F])/g, '%$2'))
 }catch(e){}
 //return
 return  '[\[' + prefixes + title + ( name ? '|'+name : '') + ']]'
}


function getPrefixes(domain){  //en.wikipedia.org -> [ 'w',  'en'] , using projPrefix{}
 domain = domain.toLowerCase() 
 var proj, isFound
 for (proj in projPrefix)  if (domain.indexOf(proj) != -1) {isFound=true; break}
 if (!isFound) return null 
 var prefix = projPrefix[proj], lang = ''
 if (prefix == '*') prefix = domain.split('.')[0] // .wikimedia.org project
 else if ((domain=domain.replace(proj, '')) && (domain != 'www.')) lang = domain.split('.')[0] //multi-lang project
 //else if (prefix.charAt(0) == ':'){ //multi-lang project   if (pp.length == 3) lang = pp[0]
 return [prefix, lang]
}

}