User:Js/urldecoder.js
Appearance
< User:Js
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
![]() | This user script seems to have a documentation page at User:Js/urldecoder. |
function urlDecoderButton(){
addFuncButton2('urlDecoder', urlDecoderRun, '/media/wikipedia/commons/9/91/Link_go.png', 'Decode URL before cursor or all URLs in selected text', window.urlDecoderKey)
}
if (wgAction=='edit' || wgAction=='submit') addOnloadHook(urlDecoderButton)
function addFuncButton2(id, func, img, title, akey){
if (window.wgWikiEditorEnabledModules && wgWikiEditorEnabledModules.toolbar){ //new
var msg = {}; msg[id] = title; mw.usability.addMessages(msg)
// $j('#wpTextbox1').wikiEditor('addToToolbar', { section:'main', groups: {'ruwp':{}}})
$j('#wpTextbox1').wikiEditor('addToToolbar', {
section:'main', //groups: {'mytools':{}},
group:'insert', tools: {id:{
type:'button',
action: {type:'callback', execute: func},
labelMsg:id,
icon:img
}}})
}else{ //old
var tlb_ = document.getElementById('toolbar')
if (!tlb_) return
var i=document.createElement('img')
i.className='mw-toolbar-custombutton'; i.id=id
i.onclick=func; i.src=img; i.title=title; i.alt=title.substr(0,3)
appendCSS('img.mw-toolbar-custombutton {height:20px; background-color:#bce; border:1px outset #bce; margin:0 1px; cursor:pointer}')
tlb_.appendChild(i)
if (akey){ i.accessKey = akey; i.title += ' ['+akey+']'; updateTooltipAccessKeys([i]) }
}
}
function urlDecoderRun(){ //main function
var httpRegExp = '(https?:\\/\\/[^\\]\\[\\n\\r<>" ]+)' // except []<>"
var beforeCursor = new RegExp('(\\[{0,2})'+httpRegExp+'( +[^\\]\n]+)?\\]{0,2}$', 'i')
var localPrefix = WMPrefixes(unSecure(wgServer+wgScript))
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', - 1500)
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-1500>0?endPos-1500: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){//finds http:.* in string, returns its length and also newText var
isBeforeCursor = true
var pos = str.lastIndexOf('http://')
if (pos == -1) pos = str.lastIndexOf('https://')
if (pos == -1) return 0
if (pos >= 2) str = str.substring(pos-2) //move left to include leading [s
var ma = str.match(beforeCursor) // result: (whole string)' '[', 'http:...', ' name]'
if (!ma) return 0
if (ma[3]) //link with name: automatically add brackets
newText = simplifyMatched(ma[0], '[', ma[2], ma[3]+']')
else //just url: add closing bracket only if there is leading bracket
newText = simplifyMatched(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'),
simplifyMatched)
if (window.urlDecoderIntLinks){
var ut = 'user_talk' //skip user_talk, usually in sig
if (window.wgFormattedNamespaces) ut = wgFormattedNamespaces[3].replace(/ /g,'_')
ut = RegExp ('\\[\\[' + ut.toLowerCase() + ':[^#]+$', 'i')
txt = txt.replace(/\[\[[^\]\|\n]+/g, function(lnk){
return ut.test(lnk) ? lnk : decodeAnchor(lnk)
})
}
return txt
}
function simplifyMatched(str, bracket, url, rest){//arguments: (whole string), '[', url, ' name]'; calls decodeUrl
if (!bracket){//no brackets, just url
var trail = url.match(RegExp('[,;\\\\\.:!\\?' //trailing punctuation, per Parser.php
+ (!/\(/.test(url) ? '\\)' : '') + ']+$' )) //trailing no-matching )
if (trail) url = url.substring(0, url.length-trail[0].length) //move these out of url
return decodeUrl(url) + str.substring(url.length)
}else if (rest) //both brackets and possibly name
return decodeUrl(url, rest.replace(/\]+$|^ +| +$/g,'')) //trim ending brackets and spaces in 'name]'
else return str //probably broken wikicode in selected text
}
function decodeUrl(url, name){ //url -> %-decoded -> [[link|name]] (if possible); name is optional
url = unSecure(url)
if (url.indexOf('%') != -1) try { url = decodeURI(url) } catch(e){} //decode %
url = url.replace(/%(3B|2F|2C|3A)/g, decodeURIComponent) //decode ;/,:
url = url.replace(/[ <>"\[\]]/g, encodeURIComponent) //" disallowed chars
if (isBeforeCursor)
for (var n in window.urlDecoderEngNames) //to eng keywords
url = url.replace(RegExp('(title=|wiki\/)('+urlDecoderEngNames[n]+':)'), '$1' + n + ':')
var link
if (!/(\}\}|\|)$/.test(url)) link = toWikilink(url) //trailing | or }} can be a part of template, skip to be safe
if (!link && window.urlDecoderCustom
&& (link = urlDecoderCustom(url)) && /^(https?:\/\/|\{\{)/.test(link))
{url = link; link = null} //still external
if (link){
link = link.replace(/%(3f|26|22)/ig, decodeURIComponent) //decode ?&"
if ((wgNamespaceNumber==0 || wgNamespaceNumber==14)
&& isBeforeCursor)
link=link.replace(/^:/,'') //probably interwiki
return '[\[' + link + (name?'|'+name:'') + ']]'
}
if (isBeforeCursor || typeof name == 'string')
url = url.replace(/''/g,'%27%27')//techically '' means the end of URL, but more likely it's part of it
if (typeof name == 'string') return '[' + url + (name?' '+name:'') + ']' //empty name
else return url
}
function toWikilink(url){//url -> wikilink, otherwise null
//try bugzilla and user-defined prefixes
if (!window.urlDecoderPrefixes) urlDecoderPrefixes = {}
urlDecoderPrefixes['https://bugzilla.wikimedia.org/show_bug.cgi?id=']='mediazilla'
for (var key in urlDecoderPrefixes)
if (url.toLowerCase().indexOf(key)!=-1)
return urlDecoderPrefixes[key]+':'+ url.substring(url.indexOf(key)+key.length)
//try WM prefixes
var parts = url.substring(7).split('/')
if (parts[1]!='wiki' || url.indexOf('?')!=-1) return null
var linkPrefix = WMPrefixes(url.toLowerCase()), prefixes = ''
if (!linkPrefix) return null
var title = url.substring(parts[0].length + parts[1].length + 9) //get part after /wiki/
title = decodeAnchor(title)
if (linkPrefix[0] && (linkPrefix[0] != localPrefix[0])) prefixes = linkPrefix[0]
if (linkPrefix[1] && (linkPrefix[1] != localPrefix[1])) prefixes += ':' + linkPrefix[1]
if (prefixes || isColonNeeded(title)) prefixes += ':' //dividing colon or cat/file leading colon
return prefixes + title
}
function decodeAnchor(link){//simplify internal link: replace %20 and _ then decode anchor
link = link.replace(/(_|%20)/g, ' ').replace(/^ +| +$/g, '')
var parts = link.split('#')
if (parts.length != 2) return link //no anchor
var anchor = parts[1], hidIdx = -1, hidden = []
//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)
anchor = anchor.replace( //hide IPs
/(?:^|[^0-9A-F\.])(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 1-byte chars: all symbols except -.:_ and []{} prohibited in links
anchor = anchor.replace(/\.[2-7][0-9A-F]/g, function(hhh){
var ch = deChar(hhh)
if ('!"#$%&\'()*+,/;<=>?@\\^`~'.indexOf(ch) >= 0) return ch; else return hhh
})
//unhide IPs and return
for (var i=hidIdx; i>=0; i--) anchor = anchor.replace('\x01'+i+'\x02', hidden[i])
if (anchor.indexOf("''") != -1) return link //cannot have double '' in link
else return parts[0] + '#' + anchor
function deChar(ss){
try{ss = decodeURIComponent(ss.replace(/\.([0-9A-F][0-9A-F])/g, '%$1'))} catch(e){}
return ss
}
}
function WMPrefixes(url){ // htp://en.wikipedia.org/wiki/... -> [ 'w', 'en']
var dd = url.substring(7).split('/')[0].split('.') // -> ['en','wikipedia','org']
if (dd.pop() != 'org') return null
var proj='', lang = '', part = dd.pop()
if (proj = {'mediawiki':'mw','wikimediafoundation':'foundation'}[part]);
else if (proj = {'wikipedia':'w','wikibooks':'b','wikinews':'n','wikiquote':'q',
'wikisource':'s','wikiversity':'v','wiktionary':'wikt'}[part]){
lang = dd.pop()
if (!lang || lang=='www') lang = ''
else if (lang=='test') {lang=''; proj='testwiki'}
}else if (part == 'wikimedia'){
part = dd.pop()
if (!part || part=='www') proj = 'foundation'
else if (/^(meta|commons|incubator|species|strategy)$/.test(part)) proj = part
else return null
}else return null
return [proj, lang]
}
function unSecure(url){
return url.replace(/https:\/\/secure\.wikimedia\.org\/(\w+)\/(\w+)\/([^\]\|\n\r ]+)/,
'http://$2.$1.org/$3')
}
function isColonNeeded(pg){
if (pg.indexOf(':')==-1) return false
else return RegExp('^('+getDecoderNS()+'|file|category) *:','i').test(pg)
}
function getDecoderNS(){
if (!window.urlDecoderNS) var urlDecoderNS = {}
urlDecoderNS.en = 'image'
var ns = urlDecoderNS[wgContentLanguage]
if (typeof ns == 'string') return ns //user-defined list
if (!window.wgNamespaceIds) {
alert('Warning: wgNamespaceIds not defined, old MediaWiki version?'); return ''
}
ns = ''
for (var name in wgNamespaceIds)
if (wgNamespaceIds[name]==6 || wgNamespaceIds[name]==14)
ns += '|' + name
ns = ns.substring(1)
urlDecoderNS[wgContentLanguage] = ns
return ns
}
}