/* CSS rules for use with [[User:Anomie/linkclassifier.js]]. To include these rules,
* insert the following into your [[Special:Mypage/monobook.js]] (yes, monobook.js not monobook.css):
importStylesheet('User:Anomie/linkclassifier.css'); // Linkback: [[User:Anomie/linkclassifier.css]]
* Please keep the linkback comment so I can know who is using this.
*/
A { color:#0033cc; }
A.stubcls { color:#6000bf; }
A.new { color:#bf0000; }
A.redirect { color:#00bf00; }
A.self-redirect { background-color:#88ff88; }
A.disambiguation { background-color:#ffff88; }
A.intentional-disambiguation { background-color:#ffffcc; }
A.soft-redirect-cats { background-color:#ffff88; }
A.deletion { color:#ff0088; }
A.broken-redirect { color:#bf0000; background-color:#88ff88; }
#bodyContent a.external, #bodyContent a.extiw { color:#338ebb; }
A:visited { color:#4365cc; }
A.stubcls:visited { color:#7f3ebf; }
A.new:visited { color:#bf3e3e; }
A.redirect:visited { color:#3ebf3e; }
A.deletion:visited { color:#ff54af; }
A.broken-redirect:visited { color:#bf3e3e; background-color:#88ff88; }
#bodyContent a.external:visited, #bodyContent a.extiw:visited { color:#5f9cbb; }
A.unprintworthy:not(.unprintworthy-shortcut) { outline:1px dotted #ff0000; }
A.image.redirect > IMG { outline:2px solid #00bf00; } /* Doesn't work, because the generated link goes to the redirect target */
A.image.nonfree-media > IMG { outline:3px double #ff0000; }
A.image.deletion > IMG { outline:2px solid #ff0088; }
A.image.deletion:visited > IMG { outline-color:#ff54af; }
/* Images can be inserted after links with the ":after" pseudo-element, although this doesn't work in IE <8. */
/*
A.featured-content:after {
content:url(//up.wiki.x.io/wikipedia/commons/thumb/b/bc/Featured_article_star.svg/12px-Featured_article_star.svg.png);
}
A.protection-edit-sysop-indef:after {
content:url(//up.wiki.x.io/wikipedia/commons/thumb/4/48/Padlock-red.svg/12px-Padlock-red.svg.png);
}
*/
A.nonimage.protection-create-sysop-indef:after {
content:url(//up.wiki.x.io/wikipedia/commons/thumb/a/a0/Padlock-skyblue.svg/12px-Padlock-skyblue.svg.png);
}
/* If you're wanting to put multiple images after, you'll need to give specific
* rules for each combination, something like this:
A.featured-content.protection-edit-sysop-indef:after {
content:url(//up.wiki.x.io/wikipedia/commons/thumb/b/bc/Featured_article_star.svg/12px-Featured_article_star.svg.png) url(//up.wiki.x.io/wikipedia/commons/thumb/4/48/Padlock-red.svg/12px-Padlock-red.svg.png);
}
*/
/* If you want to use this script, simply add the following line to your monobook.js:
importScript('User:Anomie/ajaxpreview.js'); // Backlink: [[User:Anomie/ajaxpreview.js]]
* (Please keep the comment so I can see how many people use this).
*/
var AJAXPreview={
node:null,
txt:null,
timer:null,
idx:0,
spinner:function(){
switch(AJAXPreview.idx++){
case 0:
AJAXPreview.node.innerHTML='<center style="font-size:50pt">|</center>';
break;
case 1:
AJAXPreview.node.innerHTML='<center style="font-size:50pt">/</center>';
break;
case 2:
AJAXPreview.node.innerHTML='<center style="font-size:50pt">–</center>';
break;
case 3:
AJAXPreview.node.innerHTML='<center style="font-size:50pt">\\</center>';
AJAXPreview.idx=0;
break;
}
AJAXPreview.node.style.display='block';
},
callback:function(r){
if(AJAXPreview.timer) window.clearInterval(AJAXPreview.timer);
AJAXPreview.timer=null;
if(!r.parse || !r.parse.text || !r.parse.text['*']){
AJAXPreview.node.innerHTML='<div style="border:1px solid #f00;background-color:#fcc;color:#f00;text-align:center">Bad response</div>';
throw new Error('Bad response');
}
AJAXPreview.node.innerHTML=r.parse.text['*']+'<br />';
AJAXPreview.node.style.display='block';
// Set a timeout to allow the browser a chance to parse the innerHTML
window.setTimeout(function(){
mw.hook( 'wikipage.content' ).fire( $( AJAXPreview.node ) );
for(var i=AJAXPreview.$OnLoadHooks.length-1; i>=0; i--)
AJAXPreview.$OnLoadHooks[i].call(window, AJAXPreview.node);
}, 250);
},
doError:function(xhr,textStatus,errorThrown){
if(AJAXPreview.timer) window.clearInterval(AJAXPreview.timer);
AJAXPreview.timer=null;
while(AJAXPreview.node.firstChild) AJAXPreview.node.removeChild(AJAXPreview.node.firstChild);
var d=document.createElement('DIV');
d.style.border='1px solid #f00';
d.style.backgroundColor='#fcc';
d.style.color='#f00';
d.style.textAlign='center';
d.appendChild(document.createTextNode('AJAX Error: '+textStatus+' '+errorThrown));
AJAXPreview.node.appendChild(d);
AJAXPreview.node.style.display='block';
throw new Error('AJAX error: '+textStatus+' '+errorThrown);
},
doPreview:function(ev){
if(!ev) ev=window.event;
var txt=AJAXPreview.getTextContent();
var refs=AJAXPreview.getRefs(txt);
var need=[];
var groups={};
for(var g in refs){
groups[g]='';
for(var n in refs[g]){
if(refs[g][n].text===null) need.push([g,n]);
}
}
var doPreview2=function(wikitext,sts,xhr){
if(wikitext){
refs=AJAXPreview.getRefs(wikitext);
for(var i=need.length-1; i>=0; i--){
var x=refs[need[i][0]][need[i][1]];
if(!x) continue;
if(x.type=='tag'){
groups[need[i][0]]+='\x7b\x7b#tag:ref|'+x.text+'|name='+need[i][1]+'|group='+need[i][0]+'\x7d\x7d';
} else {
groups[need[i][0]]+='\x3cref name="'+need[i][1]+'" group="'+need[i][0]+'"\x3e'+x.text+'\x3c/ref\x3e';
}
}
}
txt+='\n\n\x7b\x7b-\x7d\x7d\n----\n';
for(var g in groups){
txt+='\n;'+(g?'Group '+g:'References')+'\n\x7b\x7breflist|2|group='+g+'|refs='+groups[g]+'\x7d\x7d';
}
jQuery.ajax({
url:mw.util.wikiScript('api'),
dataType:'json',
type:'POST',
data:{
format:'json',
action:'parse',
pst:1,
text:txt,
title:mw.config.get('wgPageName'),
prop:'text',
disableeditsection:1,
preview:1,
templatesandboxtitle:mw.config.get('wgPageName'),
templatesandboxtext:txt
},
success:AJAXPreview.callback,
error:AJAXPreview.doError
});
};
mw.loader.using('mediawiki.util', function(){
if(need.length>0){
jQuery.ajax({
url:mw.util.wikiScript('index'),
dataType:'text',
type:'GET',
data:{ action:'raw', title:mw.config.get('wgPageName') },
success:doPreview2,
error:AJAXPreview.doError
});
} else {
doPreview2(null,null,null);
}
});
var x=document.getElementById('wikiDiff');
if(x) x.parentNode.removeChild(x);
if(AJAXPreview.timer) window.clearInterval(AJAXPreview.timer);
AJAXPreview.timer=window.setInterval(AJAXPreview.spinner, 250);
this.blur();
window.scrollTo(0,0);
if(ev){ // OOUI may not have an event here
if(ev.preventDefault) ev.preventDefault();
if(ev.stopPropagation) ev.stopPropagation();
ev.returnValue=false;
ev.cancelBubble=true;
}
return false;
},
getRefs:function(txt){
var g;
var refs={};
// The new "list-defined references" have to be handled specially,
// which means we have to manage to pull them out of the wikitext. Fun.
// First, do the XML-style tags.
txt=txt.replace(/<references((?:\s+[^>]*[^\/>])?)(?:\/>|>((?:.|[\r\n])*?)(<\/references>|$))/ig, function(x,p,t,c){
p=p.replace(/\s+$/g,'');
g=p.match(/\sgroup="([^\x22]*)"/i);
if(!g) g=p.match(/\sgroup='([^\x27]*)'/i);
if(!g) g=p.match(/\sgroup=(\S*)/i);
g=g?g[1]:'';
refs=AJAXPreview.getRefs2(t,g,refs);
return '';
});
// Next, to reflist and #tag:references
txt=AJAXPreview.process_templates(txt,function(n,p,o){
var c=null, g='';
if(n=='Reflist'){
for(var j=0; j<p.length; j++){
var m=p[j].match(/^\s*refs\s*=\s*((?:.|[\r\n])*?)\s*$/);
if(m) c=m[1];
var m=p[j].match(/^\s*group\s*=\s*([\x22\x27]?)([^\x22\x27]+?)\1\s*$/);
if(m) g=m[2];
}
if(c===null) c='';
} else if(/^#tag:\s*references$/i.test(n)){
c=p.length ? p.shift() : '';
for(var j=0; j<p.length; j++){
var m=p[j].match(/^\s*group\s*=\s*([\x22\x27]?)([^\x22\x27]+?)\1\s*$/);
if(m) g=m[2];
}
} else {
return null;
}
refs=AJAXPreview.getRefs2(c,g,refs);
return '';
});
return AJAXPreview.getRefs2(txt,'',refs);
},
getRefs2:function(txt,defgroup,refs){
var g,n;
// First, pull out regular <refs>. We can do this with a regex.
txt.replace(/<ref((?:\s+\S+=(?:"[^\x22]*"|'[^\x27]*'|\S*?))*)\s*(?:\/>|>((?:.|[\r\n])*?)<\/ref>)/ig, function(x,p,t){
g=p.match(/\sgroup="([^\x22]*)"/i);
if(!g) g=p.match(/\sgroup='([^\x27]*)'/i);
if(!g) g=p.match(/\sgroup=(\S*)/i);
g=g?g[1]:defgroup;
if(typeof(refs[g])=='undefined') refs[g]={};
n=p.match(/\sname="([^\x22]*)"/i);
if(!n) n=p.match(/\sname='([^\x27]*)'/i);
if(!n) n=p.match(/\sname=(\S*)/i);
if(!n) return null;
n=n[1];
if(typeof(refs[g][n])=='undefined') refs[g][n]={text:null,type:'?'};
if(refs[g][n].text===null && typeof(t)!='undefined' && t!=='' && t!==null){
refs[g][n].text=t;
refs[g][n].type='ref'
}
return null;
});
// Second, if it looks like there are #tag refs, parse them too
AJAXPreview.process_templates(txt,function(nm,p,o){
if(!/^#tag:\s*ref$/i.test(nm)) return null;
g=defgroup; n=null;
for(var j=p.length-1; j>=1; j--){
var m=p[j].match(/^\s*group\s*=\s*([\x22\x27]?)([^\x22\x27]+?)\1\s*$/);
if(m) g=m[2];
var m=p[j].match(/^\s*name\s*=\s*([\x22\x27]?)([^\x22\x27]+?)\1\s*$/);
if(m) n=m[2];
}
if(typeof(refs[g])=='undefined') refs[g]={};
if(n!==null){
if(typeof(refs[g][n])=='undefined') refs[g][n]={text:null,type:'?'};
if(refs[g][n].text===null && p[0]!==''){
refs[g][n].text=p[0];
refs[g][n].type='tag'
}
}
return null;
});
return refs;
},
process_templates:function(txt,cb,data){
var stack=[], i=0;
while(i<txt.length){
var x=stack.length?stack[stack.length-1]:null;
var xb=null;
for(var j=0; j<stack.length; j++){
if(stack[j].char=='\x5b') xb=stack[j];
}
if(txt.substr(i,2)=='\x7b\x7b'){
var ct;
for(ct=2; txt.substr(i+ct,1)=='\x7b'; ct++);
stack.push({char:'\x7b',start:i,count:ct,pstart:i+ct,params:[]});
i+=ct;
} else if(txt.substr(i,2)=='\x5b\x5b'){
var ct;
for(ct=2; txt.substr(i+ct,1)=='\x5b'; ct++);
stack.push({char:'\x5b',start:i,count:ct,pstart:i+ct,params:[]});
i+=ct;
} else if(x && x.char=='\x7b' && txt.substr(i,2)=='\x7d\x7d'){
var ct;
for(ct=2; txt.substr(i+ct,1)=='\x7d'; ct++);
if(ct>x.count) ct=x.count;
i+=ct;
x.params.push(txt.substring(x.pstart,i-ct));
// First, parse out variables
while(ct>=3){
x.count-=3;
ct-=3;
var s=x.start-x.count;
x.params=[txt.substring(s,i-x.count)];
}
// Any left is templates
while(ct>=2){
x.count-=2;
ct-=2;
var s=x.start+x.count;
var orig=txt.substring(s,i-ct);
var name=x.params.shift();
var oname=name;
name=name.replace(/_/g,' ');
name=name.replace(/^\s+|\s+$/g,'');
name=name.replace(/ +/g,' ');
name=name.replace(/^Template\s*:\s*/ig,'');
name=name.substr(0,1).toUpperCase()+name.substr(1);
var ret=cb(name, x.params, orig, data, oname);
if(ret===null){
x.params=[orig];
} else {
ret=""+ret;
var d=(ret=='' && (s==0 || txt.substr(s-1,1)=='\n') && txt.substr(i-ct,1)=='\n')?1:0;
txt=txt.substr(0,s)+ret+txt.substr(i-ct+d);
i=s+ret.length+ct;
x.params=[ret];
}
}
if(x.count<2){
stack.pop();
} else {
// The one we just completed might not be the end of the
// param, so reset the param array and pstart
x.params=[];
x.pstart=x.start+x.count;
}
} else if(xb && txt.substr(i,2)=='\x5d\x5d'){
// Drop any pending templates, they're not really templates
while(stack[stack.length-1]!=xb) stack.pop();
var ct;
for(ct=2; txt.substr(i+ct,1)=='\x5d'; ct++);
if(ct>xb.count) ct=xb.count;
i+=ct;
xb.count-=ct;
if(xb.count<2){
stack.pop();
} else {
// The one we just completed might not be the end of the
// param, so reset the param array and pstart
xb.params=[];
xb.pstart=xb.start+xb.count;
}
} else if(x && txt.substr(i,1)=='|'){
x.params.push(txt.substring(x.pstart,i));
x.pstart=++i;
} else {
i++;
}
}
return txt;
},
onLoad:function(){
var action=mw.config.get('wgAction');
if(action!='edit' && action!='submit') return;
var editForm=document.getElementById('editform');
if(!editForm) return;
var sectionField = editForm.elements['wpSection'];
var isSection=(sectionField && sectionField.value!="");
var p=editForm.elements["wpPreview"];
if(!p) return;
AJAXPreview.node=document.getElementById('wikiPreview');
if(!AJAXPreview.node) return;
AJAXPreview.txt=editForm.elements["wpTextbox1"];
if(!AJAXPreview.txt) return;
mw.loader.using( [ 'oojs-ui-core' ] ).done( function () {
var b = new OO.ui.ButtonWidget( {
label: 'Ajax Preview'+(isSection?' w/Refs':''),
tabIndex: p.tabIndex
} );
b.on( 'click', AJAXPreview.doPreview );
$( p ).before( b.$element, ' ' );
} );
p.value='Preview';
// Hooks for standard functions
if(typeof(window.createCollapseButtons) == 'function')
AJAXPreview.AddOnLoadHook(createCollapseButtons);
if(typeof(window.createNavigationBarToggleButton) == 'function')
AJAXPreview.AddOnLoadHook(createNavigationBarToggleButton);
},
getTextContent:function(){
return AJAXPreview.txt.value;
},
// Add callback functions here.
AddOnLoadHook:function(f){
AJAXPreview.$OnLoadHooks.push(f);
},
$OnLoadHooks:[]
};
$(document).ready(AJAXPreview.onLoad);
importScript('Wikipedia:AutoEd/complete.js'); // Backlink: [[Wikipedia:AutoEd/complete.js]]