MediaWiki:Gadget-urldecoder.js

[http://www.wikizamki.org/links.htm]

Версия от 08:09, 11 июля 2009; Elden (обсуждение | вклад)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Замечание: Чтобы после сохранения сделанные изменения вступили в силу, очистите кеш своего браузера: Mozilla / Firefox: Ctrl+Shift+R, IE: Ctrl+F5, Safari: Cmd+Shift+R, Konqueror: F5, Opera: через меню Tools→Preferences.

//[[ВП:Гаджеты/Упрощение ссылок]]
 
function urlDecoderButton(){
 var tlb = document.getElementById('toolbar')
 if (!tlb) return
 var bt = document.createElement('input')
 bt.type = 'button'; bt.onclick = urlDecoderRun;  bt.id = 'urlDecoder'
 bt.value = '%%';  
 bt.title = 'Раскодировать URL перед курсором или все URL в выделенном тексте'
 bt.style.cssText = 'background:#adbede; height:22px; vertical-align:top; padding:0'
 tlb.appendChild(bt)
 if (!window.urlDecoderKey) return
 bt.accessKey = urlDecoderKey
 bt.title += ' ['+urlDecoderKey+']'
 updateTooltipAccessKeys([bt])
}
if (wgAction=='edit' || wgAction=='submit') addOnloadHook(urlDecoderButton)
 
 
 
function urlDecoderRun(){ //main function
 
var httpRegExp = '(https?:\\/\\/[^\\]\\[\\n\\r<>" ]+)' //  except []<>"
var beforeCursor = new RegExp('(\\[{0,2})'+httpRegExp+'( +[^\\]\n]+)?\\]{0,2}$', 'i') 
var localPrefix = getPrefixes(wgServer.substring(7))
if (wgServer == 'https://secure.wikimedia.org')
  localPrefix = getPrefixes(wgScript.split('/')[2]+'.'+wgScript.split('/')[1]+'.org')
var newText, linkSize, txtarea = document.editform.wpTextbox1
var isBeforeCursor = false
 
if (document.selection) { //IE/Opera
  var scrollTop = document.documentElement.scrollTop
  txtarea.focus()
  range = document.selection.createRange()
  if (!range.moveStart) return
  if (range.text){
    newText = processSelText(range.text)
  }else { //no selection
    if (!(rr=range.duplicate())) return
    rr.moveStart('character', - 1000)
    linkSize = processBeforeCursor(rr.text)
    if (!linkSize) return
    range.moveStart('character', - linkSize) //select matched
  }
  //replace text
  if (newText != range.text){
    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){
    newText = processSelText(txt.substring(startPos, endPos))
  }else{ //no selection
	linkSize = processBeforeCursor(txt.substring((endPos-1000>0?endPos-1000:0), endPos))
    if (!linkSize) return
    startPos = endPos - linkSize //select matched
  }
  //replace text
  if (newText != txt.substring(startPos, endPos)){
    txtarea.value = txt.substring(0, startPos) + newText +	txt.substring(endPos, txtarea.value.length)
    txtarea.selectionEnd = startPos + newText.length
    txtarea.selectionStart = startPos
  }
  txtarea.scrollTop = scrollTop
}//end of main function
 
 
function processBeforeCursor(str){ //looks  for http: inside string, returns it's distance to cursor, also sets newText var
 isBeforeCursor = true
 var pos = str.lastIndexOf('http://') //to cut out possible preceding http links
 if (pos == -1) pos = str.lastIndexOf('https://')
 if (pos == -1) return 0
 else if (pos > 10) str = str.substring(pos-2) //cut chars before http, leaving some room for possible [
 var ma = str.match(beforeCursor) // result: (whole string)' '[', 'http:...', ' name]'
 if (!ma) return 0
 if (ma[3]) //link with name: add brackets just in case
   newText = decodeMatchedLink(ma[0], '[', ma[2], ma[3]+']')
 else //just url: add closing bracket if there is leading bracket
   newText = decodeMatchedLink(ma[0], ma[1], ma[2], ma[1]?']':'')
 return ma[0].length
}
 
function processSelText(txt){
 txt = txt.replace(RegExp('(\\[{0,2})' + httpRegExp + '([^\\]\\[\\n\\r]*?\\]\\]?)?', 'ig'),
  decodeMatchedLink)
 if (window.urlDecoderIntLinks) txt = txt.replace(/\[\[[^\]\|\n]+/g, 
  function(lnk){
   return /^\[\[user_talk:[^#]+$/i.test(lnk) ? lnk : decodeWikiLink(lnk)
 })
 return txt
}
 
 
function decodeMatchedLink(str, bracket, url, rest){//gets: (whole string), '[', url, ' name]'
 if (!bracket){
   if (/\}\}$/.test(url)) return str //http://...}}  - probably a part of template call
   return decodeLink(url) + str.substring(url.length) //just url
 }
 if (!rest) return str //no matching closing bracket
 var name = rest.replace(/^ +|\]+$/g,'') //trim leading spaces and ending brackets
 str = decodeLink(url, name)
 if (str.charAt(0) != '[' ) str = '['+str+']' //not wikilink - restore single brackets
 return str
}
 
 
function decodeLink(url, name){ //name is optional
 var parts, endingDots, result
 if (name) name = name.replace(/^ +| +$/g,'') //trim spaces
 //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]+ (name?'|'+name:'') + ']]'
 
 //decode %
 if (url.indexOf('%') != -1) try { url = decodeURI(url) } catch(e){}
 url = url.replace(/%(3B|2F|2C|3A)/g, function(s){return decodeURIComponent(s)}) // ;/,:
 //encode back some chars not allowed by MediaWiki
 url = url.replace(/[ <>"\[\]]/g, function(s){return encodeURIComponent(s)}) //"
 
 if (isBeforeCursor) 
   for (var n in window.urlDecoderEngNames) //to eng keywords
     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 title = url.substring(parts[0].length + parts[1].length + 9) //get part after  /wiki/
 title = decodeWikiLink(title)
 var prefixes = ''
 if (linkPrefix[0] && (linkPrefix[0] != localPrefix[0])) prefixes += linkPrefix[0]
 if (linkPrefix[1] && (linkPrefix[1] != localPrefix[1])) prefixes += ':'+linkPrefix[1]
 if (prefixes) prefixes += ':'
 if (!prefixes && isColonNeeded(title)) prefixes = ':' //leading colon for cat/file 
 //return result
 result = '[\[' + prefixes + title
 if (name) result += '|' + name + ']]'
 else result = (result + ']]').replace(/(\.+)\]\]/,']]$1') //url.  -> [[w]].  not [[w.]]
 return result
}
 
function decodeWikiLink(link){
 link = link.replace(/_/g, ' ').replace(/^ +| +$/g, '')
 var parts = link.split('#')
 if (parts.length != 2) return link
 var anchor = parts[1], hidIdx = -1, hidden = []
 link = parts[0]
 anchor = anchor.replace( //hide IPs
  /(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/,
   function(s){ hidden[++hidIdx] = s; return '\x01' + hidIdx + '\x02' }
 )
 //decode 4, 3 and 2-byte: http://en.wikipedia.org/wiki/UTF-8
 anchor = anchor.replace(/\.F[0-4]\.[89AB][\dA-F]\.[89AB][\dA-F]\.[89AB][\dA-F]/g, deChar)
 anchor = anchor.replace(/\.E[\dA-F]\.[89AB][\dA-F]\.[89AB][\dA-F]/g, deChar)
 anchor = anchor.replace(/\.[CD][\dA-F]\.[89AB][\dA-F]/g, deChar)
 //decode reserved 1-byte chars: http://meta.wikimedia.org/wiki/Url , http://en.wikipedia.org/wiki/Percent_encoding
 anchor = anchor.replace(/\.[2-5][0-9A-F]/g, function(str){
   var ch = deChar(str)  // ;:@&=+$,/?%#[]<>
   if ((ch != ':') &&
     ((encodeURIComponent(ch).replace(/%/,'.') == str) || ('!*\'()'.indexOf(ch) != -1)))
     return ch
   else 
    return str //do not decode e.g. %35 which is '5' and not supposed to be encoded
 })
 function deChar(str){ return tryDecode(str.replace(/\.([0-9A-F][0-9A-F])/g, '%$1')) }  
 function tryDecode(s){ try {s = decodeURIComponent(s)} catch(e){}; return s }
 //unhide IPs
 for (var i=hidIdx; i>=0; i--) anchor = anchor.replace('\x01'+i+'\x02', hidden[i])
 //return
 return link + '#' + anchor
}
 
function getPrefixes(domain){  //en.wikipedia.org -> [ 'w',  'en'] , using projPrefix{}
 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'
 } 
 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]
}
 
function isColonNeeded(pg){
 return /^(категория|файл|изображение|category|file|image):/i.test(pg)
}
 
}