MediaWiki:Gadget-urldecoder.js
[http://www.wikizamki.org/links.htm]
(Различия между версиями)
Elden (обсуждение | вклад)
(Новая страница: «//ВП:Гаджеты/Упрощение ссылок function urlDecoderButton(){ var tlb = document.getElementById('toolbar') if (!tlb) return var bt = do…»)
(Новая страница: «//ВП:Гаджеты/Упрощение ссылок function urlDecoderButton(){ var tlb = document.getElementById('toolbar') if (!tlb) return var bt = do…»)
Текущая версия на 08:09, 11 июля 2009
//[[ВП:Гаджеты/Упрощение ссылок]] 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) } }