User:SoledadKabocha/linkclassifier.js
Appearance
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:SoledadKabocha/linkclassifier. |
/* Modified from [[User:Anomie/linkclassifier.js]]
If you want to use this script, simply add the following line to your [[Special:MyPage/common.js]] or [[Special:MyPage/skin.js]]:
importScript('User:Anomie/linkclassifier.js'); //Linkback: [[User:SoledadKabocha/linkclassifier.js]]
(Please keep the comment so I can see how many people use this). You will also want to
add some CSS rules, such as those at [[User:Anomie/linkclassifier.css]].
Note that the classes newly added to this script do not have rules in Anomie's stylesheet.
See the documentation page for a complete list of such classes.
*/
window.LinkClassifierSupportsFuncChain = true; // flag to distinguish this script from the original linkclassifier; SHOULD be read but not modified by other scripts
// These need to be global so other scripts (e.g. jsMessage) can read them (XXX: really?)
var LinkClassifierApiRequestsOutstanding = 0;
var LinkClassifierChainedFuncCalledAlready = false;
function defaultPref( cfig, dflt ) {
return ( typeof cfig == typeof dflt ? cfig : dflt );
}
window.LinkClassifierErrMsgPrefix = defaultPref( window.LinkClassifierErrMsgPrefix, '<span class="linkclassifier-error">LinkClassifier FAILED: Something went wrong with the server or your Internet connection, or you impatiently browsed to another page.</span><br />' );
var LinkClassifier={
/* This object maps classes to the categories for which to apply them. Values may be an array of strings or a regex. */
cats:{
deletion:[
'Category:All articles proposed for deletion',
'Category:All books proposed for deletion',
'Category:All disputed non-free Wikipedia files',
'Category:All orphaned non-free use Wikipedia files',
'Category:All possibly unfree Wikipedia files',
'Category:All replaceable non-free use Wikipedia files',
'Category:All Wikipedia files with no copyright tag',
'Category:All Wikipedia files with no non-free use rationale',
'Category:All Wikipedia files with unknown copyright status',
'Category:All Wikipedia files with unknown source',
'Category:Articles for deletion',
'Category:Articles on deletion review',
'Category:Candidates for speedy deletion',
'Category:Candidates for undeletion',
'Category:Categories for conversion',
'Category:Categories for deletion',
'Category:Categories for listifying',
'Category:Categories for merging',
'Category:Categories for renaming',
'Category:Categories for speedy renaming',
'Category:Categories to be listified then deleted',
'Category:Duplicate or hardcoded templates awaiting deletion',
'Category:Items pending OTRS confirmation of permission for over 30 days',
'Category:Miscellaneous pages for deletion',
'Category:Stub categories for deletion',
'Category:Stub template deletion candidates',
'Category:Templates for deletion',
'Category:Wikipedia deprecated and orphaned templates',
'Category:Wikipedia files for deletion',
'Category:Wikipedia files with unknown source for deletion in dispute',
'Category:Wikipedia templates for deletion'
].sort(),
'deletion-rfd':[
'Category:Redirects for discussion', // moved from deletion - obsolete?
'Category:All redirects for discussion'
].sort(),
disambiguation:[
'Category:All disambiguation pages'
].sort(),
'set-index':[
'Category:All set index articles'
].sort(),
'featured-content':[
'Category:Featured articles',
'Category:Featured lists',
'Category:Featured pictures',
'Category:Featured sounds',
'Category:Featured videos',
'Category:Featured portals'
].sort(),
'good-content':[
'Category:Good articles'
].sort(),
'soft-redirect':[
'Category:Wikipedia soft redirects',
'Category:Wikipedia interwiki soft redirects',
'Category:Wikipedia soft redirected project pages',
'Category:Protected soft redirects',
'Category:Wikipedia soft redirected talk pages',
'Category:Wikipedia soft redirected templates',
'Category:User soft redirects',
'Category:Redirects to Wikiquote',
'Category:Deprecated shortcuts',
'Category:Redirects to Wiktionary'
].sort(),
'soft-redirect-cats':[
'Category:Wikipedia soft redirected categories',
].sort(),
'spoken-articles':[
'Category:Spoken articles'
].sort(),
stubcls:/^Category:.* stubs$/,
'nonfree-media':[
'Category:All non-free media'
].sort(),
'no-attrib-reqd-media':[
//'Category:Cc-zero images',
'Category:CC-zero files',
//'Category:All user-created public domain images',
'Category:All User-created public domain files',
//'Category:Author died more than 100 years ago public domain images',
'Category:Author died more than 100 years ago public domain files',
//'Category:Author died more than 70 years ago public domain images',
'Category:Author died more than 70 years ago public domain files',
//'Category:Copyright holder released public domain images',
'Category:Copyright holder released public domain files',
'Category:PD OpenClipart',
'Category:PD US no notice',
'Category:PD US not renewed',
'Category:PD chem',
'Category:PD other reasons',
'Category:PD script',
'Category:PD tag needs updating',
'Category:PD-link',
'Category:Pre 1978 without copyright notice US public domain images', // still current name
'Category:Public domain art',
//'Category:Public domain images',
'Category:Public domain files',
//'Category:Public domain images ineligible for copyright',
'Category:Public domain files ineligible for copyright',
'Category:Public domain images of currency', // still current name
'Category:Public domain images of fonts', // still current name
'Category:Public domain music images', // still current name
'Category:Files copyrighted by the Wikimedia Foundation'
].sort(),
unprintworthy:[
'Category:Unprintworthy redirects',
'Category:Middle-earth redirects from redundant titles'
].sort(),
'unprintworthy-shortcut':[
'Category:Redirects from shortcuts'
].sort(),
printworthy:[
'Category:Printworthy redirects',
'Category:Redirects from systematic names',
'Category:Redirects from systematic abbreviations',
'Category:Redirects from ISO 3166 codes',
'Category:Redirects from postal abbreviations',
'Category:Redirects from scientific abbreviations',
'Category:Redirects from stock symbols',
'Category:Redirects from scientific names'
].sort(),
invalidisbn:[
'Category:Articles with invalid ISBNs',
'Category:Articles with invalid ISSNs',
'Category:Pages with ISBN errors' // applied by Citation Style 1 module, so also in cs1luaerror
].sort(),
missingisbn:[
'Category:Articles lacking ISBNs'
].sort(),
'blp-sources':/^Category:BLP articles lacking sources( from |$)/,
'blp-unreferenced':[
'Category:All unreferenced BLPs',
].sort(),
'blp-sourceimdb':/^Category:Articles sourced (only )?by IMDb( from |$)/,
'unclear-notability':[
'Category:All articles with topics of unclear notability'
].sort(),
'need-coord':[
'Category:All articles needing coordinates',
'Category:Pages with malformed coordinate tags'
].sort(),
'cleanup-translation':[
'Category:Wikipedia articles needing cleanup after translation'
].sort(),
deadend:[
'Category:All dead-end pages',
'Category:All articles with too few wikilinks',
'Category:All articles covered by WikiProject Wikify'
].sort(),
'expert-attention':[
'Category:All articles needing expert attention'
].sort(),
'user-special-block':[
'Category:Wikipedia contact role accounts',
'Category:Wikipedia maintenance scripts'
].sort(),
'user-compromised-block':[ // not 100% useful because the user(talk) pages may not exist
'Category:Compromised accounts'
].sort(),
'user-altaccount':[
'Category:Wikipedia doppelganger accounts'
].sort(),
'redirect-possibilities':[
'Category:Redirects with possibilities',
'Category:Redirects from albums',
'Category:Redirects from books',
'Category:Redirects from brand names',
'Category:Redirects from EPs',
'Category:Redirects from films',
'Category:Redirects from former names',
'Category:Redirects to list entries',
//'Category:Redirects from people', // doesn't currently contain articles
'Category:Redirects from phrases',
'Category:Redirects from products',
'Category:Redirects from school articles',
'Category:Redirects from songs',
'Category:Redirects from writers',
//'Category:Redirects from transport routes', // doesn't currently contain articles
'Category:Comics redirects with possibilities',
'Category:Redirects to decade',
'Category:Middle-earth redirects with possibilities',
'Category:Redirects from birth names',
'Category:Redirects from alternative characters',
'Category:Comics redirects to lists',
'Category:Comics redirects from related words',
'Category:Comics redirects to sections',
'Category:Middle-earth redirects to lists',
'Category:Redirects from birth names',
'Category:Redirects from historic names',
'Category:Redirects from maiden names',
'Category:Redirects from married names',
'Category:Middle-earth redirects from former names',
'Category:Characters redirects to lists',
'Category:Episode redirects to lists', // XXX: Subcats not done!
'Category:Redirected episode articles',
'Category:Fiction-based redirects to list entries',
'Category:Redirected characters articles',
'Category:Aqua Teen Hunger Force characters redirects to lists',
'Category:Courage the Cowardly Dog characters redirects to lists',
'Category:I Am Weasel characters redirects',
'Category:SpongeBob SquarePants characters redirects to lists',
'Category:The Venture Bros. characters redirects to lists',
'Category:Fictional character redirects to lists', // XXX: Subcats not done!
//'Category:Fictional element redirects to lists', // doesn't currently contain articles
'Category:Redirected fictional element articles',
'Category:Redirects from individual people',
'Category:Redirects from multiple people',
'Category:Redirects from members',
'Category:Redirects from quotations',
'Category:Redirects from slogans',
'Category:Redirects from highway routes',
'Category:Redirects from London bus routes',
'Category:Redirects from New York City area bus routes',
'Category:Redirects from railroad names with ampersands',
'Category:Redirects from highway in region' // has a "without possibilities" subcat...
].sort(),
'redirect-section':[ // Anomie said not 100% useful because a human has to manually add category
'Category:Redirects to sections',
'Category:Redirects to embedded anchors'
].sort(),
'redirect-listentry':[
'Category:Redirects to list entries' // also in -possibilities, I know
].sort(),
'redirect-incompletedab':[
'Category:Redirects from incomplete disambiguations'
].sort(),
chemobot:/^Category:(\w+boxes which contain changes to (watched|verified) fields|Articles (containing unverified chemical infoboxes|with changed (\w+ identifier|CASNo)))$/,
citeerror:/^Category:(Pages with (\w+ reference names|incorrect ref formatting|missing references list|reference errors)|Articles with incorrect citation syntax)$/,
npovdispute:[
'Category:All NPOV disputes'
].sort(),
accuracydispute:[
'Category:All accuracy disputes'
].sort(),
copyedit:[
'Category:All articles needing copy edit'
].sort(),
deadextlink:[
'Category:All articles with dead external links',
'Category:All articles with broken or outdated citations'
].sort(),
outofdate:/^Category:(Articles with obsolete information|Wikipedia articles in need of updating)( from |$)/,
nofootnotes:[
'Category:All articles lacking in-text citations'
].sort(),
'disambiguation-cleanup':/^Category:(Disambiguation pages (in need of (being split|cleanup)|to be converted to broad concept articles)|Incomplete disambiguation)( from |$)/,
'redirect-crossnamespace':[
'Category:Cross-namespace redirects',
'Category:Redirects to category space',
'Category:Redirects to help namespace',
'Category:Redirects to the main namespace',
'Category:Redirects to portal space',
'Category:Redirects to template from non-template namespace',
'Category:Redirects to project space',
'Category:Redirects to user namespace',
'Category:Redirects to talk pages'
].sort(),
'systemicbias-geo':/^Category:((Articles with (disproportional|limited)|Vague or ambiguous) geographic scope( from |$)|.+-centric$)/,
'systemicbias-time':/^Category:Articles (slanted towards recent events( from |$)|lacking historical information$)/,
'systemicbias-other':/^Category:Articles needing more viewpoints( from |$)/,
tempundelete:[
'Category:Candidates for undeletion'
].sort(),
'promotional-tone':[
'Category:All articles with a promotional tone'
].sort(),
'retracted-pub':[
'Category:Articles citing retracted publications'
].sort(),
rewrite:/^Category:Wikipedia articles needing rewrite( from |$)/,
subscriptiononly:[
'Category:Pages containing links to subscription only content'
].sort(),
povcheck:/^Category:Articles needing POV-check( from |$)/,
cs1luaerror:/^Category:(Pages (using (web )?citations with|with archiveurl cit.+ errors$|with citations ((hav|us)ing|lacking titles$)|with [A-Z]+ errors$|with empty citations$)|CS1 (errors|maint))/,
'transwiki-cleanup':[
'Category:Transwiki cleanup'
].sort(),
'template-error':[
'Category:Pages containing omitted template arguments',
'Category:Pages where expansion depth is exceeded',
'Category:Pages where node count is exceeded',
'Category:Pages where node-count is exceeded', //no longer used on WMF wikis but may be elsewhere
'Category:Pages where template include size is exceeded',
'Category:Template loop warnings'
].sort(),
'disambiguation-cats':[
'Category:Disambiguation categories'
].sort(),
luaerror:[
'Category:Pages with script errors'
].sort(),
'redirect-grammaticalnumber':/^Category:Redirects (from|to) plurals$/
},
/* This object maps page props to CSS classes for which to apply them. Values may be an array of strings or a function returning such. */
props: {
disambiguation:[
'disambiguation'
],
},
/* This regex matches page titles to be marked as intentional links to disambiguation pages */
intentionaldab: / \(disambiguation\)$/,
initUnloadHandlerIfNeeded:function( ) {
if ( window.LinkClassifierUninterruptible === true ) {
if ( ( wgAction == 'edit' || wgAction == 'submit' ) && $.compareObject( mw.user.options.get( [ 'skin' ] ), { skin: 'vector' } ) ) {
mw.util.jsMessage( 'linkclassifier: Ignoring user setting of uninterruptible mode to avoid spurious warnings saving edits in the Vector skin' );
window.LinkClassifierUninterruptible = false; // still needed?
return;
}
else {
window.LinkClassifierOldOnbeforeunload = window.onbeforeunload;
window.onbeforeunload = function (evt) {
var message = 'LinkClassifier is still waiting for API responses.';
//XXX: At least Firefox no longer shows the custom msg...
if (evt === undefined) {
evt = window.event;
}
if (evt) {
evt.returnValue = message;
}
return message;
}
}
// need to check whether the timeout already exists?
window.LinkClassifierUnloadSafetyTimeout = setTimeout( LinkClassifier.removeUnloadHandlerIfNeeded, 45000 );
if ( typeof window.LinkClassifierStatusSel == 'string' ) {
$( window.LinkClassifierStatusSel ).addClass( 'linkclassifier-unload-added' );
}
}
},
removeUnloadHandlerIfNeeded:function( ) {
if ( !window.LinkClassifierUninterruptible || window.LinkClassifierUnloadHandlerRemoved ) return;
window.onbeforeunload = window.LinkClassifierOldOnbeforeunload; // does this need a type safety check?
if ( typeof window.LinkClassifierUnloadSafetyTimeout == 'number' && window.LinkClassifierUnloadSafetyTimeout != 0 ) {
clearTimeout( window.LinkClassifierUnloadSafetyTimeout );
if ( typeof window.LinkClassifierStatusSel == 'string' ) {
var statusElement = $( window.LinkClassifierStatusSel );
statusElement.removeClass( 'linkclassifier-unload-added' );
statusElement.addClass( 'linkclassifier-unload-removed' );
}
}
window.LinkClassifierUnloadHandlerRemoved = true;
},
forceCallChainedFunc:function( ) {
if ( !LinkClassifierChainedFuncCalledAlready && typeof( window.LinkClassifierChainedFunc ) === 'function' ) {
LinkClassifierChainedFuncCalledAlready = true;
if ( window.LinkClassifierChainedFuncArg === undefined ) {
LinkClassifierChainedFunc();
}
else {
LinkClassifierChainedFunc( window.LinkClassifierChainedFuncArg );
}
}
LinkClassifier.removeUnloadHandlerIfNeeded( );
if ( typeof window.LinkClassifierStatusSel == 'string' ) {
var statusElement = $( window.LinkClassifierStatusSel );
statusElement.removeClass( 'linkclassifier-started' );
statusElement.addClass( 'linkclassifier-finished' );
}
},
// should be renamed "finalizeRequest" or similar
maybeCallChainedFunc:function(xhr, sts){
if ( LinkClassifierApiRequestsOutstanding <= 0 ) {
if ( typeof window.LinkClassifierStatusSel == 'string' ) {
var statusElement = $( window.LinkClassifierStatusSel );
statusElement.removeClass( 'linkclassifier-started' );
statusElement.addClass( 'linkclassifier-aborted' );
}
if ( window.console !== undefined && typeof(window.console.error)=='function' ) {
window.console.error( 'linkclassifier: Finished more API requests than started (maybe multiple copies are running)?! (curr=' + LinkClassifierApiRequestsOutstanding + ')' );
}
mw.util.jsMessage( 'linkclassifier: Finished more API requests than started<br />(maybe multiple copies are running)?!<br />(curr=' + LinkClassifierApiRequestsOutstanding + ')' );
}
else --LinkClassifierApiRequestsOutstanding;
if ( LinkClassifierApiRequestsOutstanding <= 0 ) {
LinkClassifier.forceCallChainedFunc( );
}
},
callback:function(r, sts, xhr){
if(!r.query) {
LinkClassifier.removeUnloadHandlerIfNeeded( );
if ( typeof window.LinkClassifierStatusSel == 'string' ) {
var statusElement = $( window.LinkClassifierStatusSel );
statusElement.removeClass( 'linkclassifier-started' );
statusElement.addClass( 'linkclassifier-aborted' );
}
mw.util.jsMessage( 'linkclassifier: Bad response; ' + LinkClassifierApiRequestsOutstanding + ' requests were in progress' );
if( window.console === undefined || typeof(window.console.error)!='function')
throw new Error('Bad response; ' + LinkClassifierApiRequestsOutstanding + ' requests were in progress');
window.console.error("Bad response; " + LinkClassifierApiRequestsOutstanding + ' requests were in progress', r);
return;
}
if(r['query-continue']){
mw.util.jsMessage( 'linkclassifier DEBUG: Query is continuing' );
var cc=this.rawdata;
for(var k in r['query-continue']){
for(var k2 in r['query-continue'][k]){
cc[k2]=r['query-continue'][k][k2];
}
}
LinkClassifierApiRequestsOutstanding++;
$.ajax({
url:mw.util.wikiScript('api'),
dataType:'json',
type:'POST',
data:cc,
rawdata:cc,
success:LinkClassifier.callback, // recurse
error:function(xhr,textStatus,errorThrown){
LinkClassifier.removeUnloadHandlerIfNeeded( );
if ( typeof window.LinkClassifierStatusSel == 'string' ) {
var statusElement = $( window.LinkClassifierStatusSel );
statusElement.removeClass( 'linkclassifier-started' );
statusElement.addClass( 'linkclassifier-aborted' );
}
var errTxt = 'AJAX error (callback query-continue), with '
+ LinkClassifierApiRequestsOutstanding + ' requests in progress: '+textStatus+' '+errorThrown;
mw.util.jsMessage( window.LinkClassifierErrMsgPrefix + errTxt );
throw new Error( errTxt );
},
complete:LinkClassifier.maybeCallChainedFunc
});
}
r=r.query;
var a=document.getElementById('wikiPreview');
if(!a && $('.mw-redirectedfrom').length == 1) a=document.getElementById('mw-content-text');
if(!a) a=document.getElementById('bodyContent');
if(!a) {
LinkClassifier.removeUnloadHandlerIfNeeded( );
if ( typeof window.LinkClassifierStatusSel == 'string' ) {
var statusElement = $( window.LinkClassifierStatusSel );
statusElement.removeClass( 'linkclassifier-started' );
statusElement.addClass( 'linkclassifier-aborted' );
}
throw new Error('Huh? No body content?');
}
a=a.getElementsByTagName('A');
if(!a || a.length==0) { LinkClassifier.forceCallChainedFunc( ); return; }
var redir={};
var redirlist=[];
if(r.redirects) for(var i=r.redirects.length-1; i>=0; i--){
redir[r.redirects[i].from]=r.redirects[i].to;
redirlist.push(r.redirects[i].from);
}
if(redirlist.length>0) {
var q = {format:'json', action:'query', titles:redirlist.join('|'), prop:'categories|info', cllimit:'max', inprop:'protection', rawcontinue:1 }
LinkClassifierApiRequestsOutstanding++;
$.ajax({
url:mw.util.wikiScript('api'),
dataType:'json',
type:'POST',
data:q,
rawdata:q,
success:LinkClassifier.callback, // recurse
error:function(xhr,textStatus,errorThrown){
LinkClassifier.removeUnloadHandlerIfNeeded( );
if ( typeof window.LinkClassifierStatusSel == 'string' ) {
var statusElement = $( window.LinkClassifierStatusSel );
statusElement.removeClass( 'linkclassifier-started' );
statusElement.addClass( 'linkclassifier-aborted' );
}
var errTxt = 'AJAX error (callback redir), with '
+ LinkClassifierApiRequestsOutstanding + ' requests in progress: '+textStatus+' '+errorThrown;
mw.util.jsMessage( window.LinkClassifierErrMsgPrefix + errTxt );
throw new Error( errTxt );
},
complete:LinkClassifier.maybeCallChainedFunc
});
}
var defaultPrefix = 'redir-'; // make configurable?
var prefix=( this.rawdata.redirects ? '' : defaultPrefix );
var cats={};
var missing={};
var classes={};
var uncategorized={};
if(r.pages) { for(var i in r.pages){
classes[r.pages[i].title] = [];
missing[r.pages[i].title]=( r.pages[i].missing !== undefined );
if ( !missing[r.pages[i].title] ) {
if( r.pages[i].categories !== undefined ){
cats[r.pages[i].title]=r.pages[i].categories.map(function(a){ return a.title; }).sort();
uncategorized[r.pages[i].title]=( r.pages[i].categories.length == 0 );
}
else {
uncategorized[r.pages[i].title]=true;
}
}
if(r.pages[i].pageprops!==undefined){
for ( var k in r.pages[i].pageprops ) {
if ( !LinkClassifier.props[k] ) {
continue;
}
var v = LinkClassifier.props[k];
if ( $.isFunction( v ) ) { // TODO: What does isFunction do that typeof v == 'function' doesn't?
v = v( r.pages[i].pageprops[k], k, r.pages[i].title );
}
classes[r.pages[i].title].push.apply( classes[r.pages[i].title], v );
}
}
if(r.pages[i].protection!== undefined){
classes[r.pages[i].title]=[];
var x={};
for(var j=r.pages[i].protection.length-1; j>=0; j--){
var p=prefix+'protection-'+r.pages[i].protection[j].type+'-'+r.pages[i].protection[j].level;
if( x[p] === undefined ){
x[p]=1;
classes[r.pages[i].title].push(p);
}
if(r.pages[i].protection[j].expiry=='infinity'){
p+='-indef';
if( x[p] === undefined ){
x[p]=1;
classes[r.pages[i].title].push(p);
}
}
}
}
if(r.pages[i].flagged!==undefined){
if(r.pages[i].lastrevid!=r.pages[i].flagged.stable_revid){
classes[r.pages[i].title].push('needs-review');
}
}
}/* end of for loop */}
else {
mw.util.jsMessage( 'linkclassifier DEBUG: Got response with no matching pages' );
}
Array.prototype.forEach.call(a, function(a){
if( a.wikipage === undefined ) {
mw.util.jsMessage( 'linkclassifier DEBUG: Got undefined wikipage for link<br />' + a.href );
//should also print a.title?
return;
}
var origHref = a.href;
var curRedirMalformed = false;
if( redir[a.wikipage] !== undefined ){
$(a).addClass('redirect');
a.wikipage=redir[a.wikipage];
var newTitle='';
if ( a.wikipage != '' ) {
newTitle = a.wikipage;
var cns=mw.config.get('wgCanonicalNamespace');
if(a.wikipage==(cns?cns+':':'')+mw.config.get('wgTitle'))
$(a).addClass('self-redirect');
else if(missing[a.wikipage])
$(a).addClass('broken-redirect');
}
else {
newTitle = 'Malformed redirect (target begins with #)';
curRedirMalformed = true;
$(a).addClass('broken-redirect');
}
a.title=( window.LinkClassifierRedirTitleAppend === true ? a.title + '\nRedirects to: ' + newTitle : newTitle );
}
var m=origHref.match(/#.*/);
if(m && m[0].substr(0,10)!=="#cite_note" && !curRedirMalformed){
//HACK to avoid overwriting tooltips already modified by [[User:SoledadKabocha/markBlockedPlus.js]] (or the original markblocked)
//TODO: logging, as this might not always work
if ( !( typeof markBlocked == 'function' && !window.mbTipBox && $(a).hasClass('userlink') ) ) {
//Anchor unencoding. Since fromCharCode only supports the Basic Multilingual Plane, and fromCodePoint is still experimental,
//we handle only up to 3 UTF-8 bytes.
//Basic Latin (1 UTF-8 byte), avoiding control chars
var mfix = m[0].replace(/_/g,' ').replace(/\.([2-7][0-9A-F])/g, function(x,n){ return String.fromCharCode(parseInt(n,16)); });
mfix = mfix.replace(/\u007F/g, '.7F');
//2 UTF-8 bytes
var regex2b = /\.([CD][0-9A-F])\.([89AB][0-9A-F])/;
var result2b = regex2b.exec( mfix );
while ( result2b !== null ) {
var byte1 = parseInt( result2b[ 1 ], 16 );
var byte2 = parseInt( result2b[ 2 ], 16 );
var fixedCode = ( ( byte1 & 0x1F ) << 6 ) | ( byte2 & 0x3F );
mfix = mfix.replace( regex2b, String.fromCharCode( fixedCode ) );
result2b = regex2b.exec( mfix );
}
//3 UTF-8 bytes
var regex3b = /\.E([0-9A-F])\.([89AB][0-9A-F])\.([89AB][0-9A-F])/;
var result3b = regex3b.exec( mfix );
while ( result3b !== null ) {
var nibb1 = parseInt( result3b[ 1 ], 16 );
var byte2 = parseInt( result3b[ 2 ], 16 );
var byte3 = parseInt( result3b[ 3 ], 16 );
var fixedCode = ( nibb1 << 12 ) | ( ( byte2 & 0x3F ) << 6 ) | ( byte3 & 0x3F );
mfix = mfix.replace( regex3b, String.fromCharCode( fixedCode ) );
result3b = regex3b.exec( mfix );
}
a.title=a.title.replace(/#.*/,'')+mfix;
}
}
if(LinkClassifier.intentionaldab.test(a.origwikipage)){
$(a).addClass('intentional-disambiguation');
}
var shouldDetectUncat = window.LinkClassifierReallyEnableUncategorized && ( !window.LinkClassifierFilterUncategorized || !(/^((User|Talk|MediaWiki|Module|\w+ talk):|Main Page$)/.test( a.wikipage )) );
if( shouldDetectUncat && uncategorized[a.wikipage] === true ) {
$(a).addClass('uncategorized');
}
if( a.wikipage != a.origwikipage && uncategorized[a.origwikipage] === true ) {
//XXX: uncategorized test here wasn't originally type-safe...did I have a good reason?
$(a).addClass(defaultPrefix + 'uncategorized');
}
if( classes[a.wikipage] !== undefined ){
for(var j=classes[a.wikipage].length-1; j>=0; j--)
$(a).addClass(classes[a.wikipage][j]);
}
if( a.wikipage!=a.origwikipage && classes[a.origwikipage] !== undefined ){
for(var j=classes[a.origwikipage].length-1; j>=0; j--)
$(a).addClass(classes[a.origwikipage][j]);
}
var c1=[];
if( cats[a.wikipage] !== undefined ){
c1=c1.concat(cats[a.wikipage]);
}
if(a.wikipage!=a.origwikipage && cats[a.origwikipage] !== undefined ){
c1=c1.concat(cats[a.origwikipage]);
}
if(c1.length>0){
c1=c1.sort();
for(var cls in LinkClassifier.cats){
var i1=c1.length-1;
var c2=LinkClassifier.cats[cls];
if(c2 instanceof RegExp){
while(i1>=0){
if(c2.test(c1[i1])){
$(a).addClass(cls);
break;
}
i1--;
}
} else {
var i2=c2.length-1;
while(i1>=0 && i2>=0){
if(c1[i1]==c2[i2]){
$(a).addClass(cls);
break;
}
(c1[i1]>c2[i2])?--i1:--i2;
}
}
}
}
});
},
getPageName:function(url){
var m=url.match(/\/wiki\/([^?#]+)/);
if(!m) m=url.match(/\/w\/index.php\?(?:.*&)?title=([^&#]+)/);
if(!m) return '';
var t=decodeURIComponent(m[1]).replace(/_/g,' ');
if(t.substr(0,6)=='Image:') t='File:'+t.substr(6);
if(t.substr(0,11)=='Image talk:') t='File talk:'+t.substr(6);
if(t.substr(0,8)=='Special:') t='';
return t;
},
classifyChildren:function(node){
mw.loader.using(['mediawiki.util','mediawiki.user'], function(){
var fixedNode = ( node === undefined ? document.getElementById( 'wikiPreview' ) : node );
if ( !fixedNode ) fixedNode = document.getElementById( 'bodyContent' );
if ( !fixedNode ) return;
if ( typeof window.LinkClassifierStatusSel == 'string' ) {
$( window.LinkClassifierStatusSel ).addClass( 'linkclassifier-started' );
}
var a=fixedNode.getElementsByTagName('A');
if(!a || a.length==0) { LinkClassifier.forceCallChainedFunc( ); return; }
var self= LinkClassifier.getPageName(location.href);
var self2=wgPageName.replace(/_/g,' ');
a=Array.prototype.map.call(a, function(a){
a.wikipage='';
if(/(^|\s)(external|extiw)(\s|$)/.test(a.className)) return '';
if(!/(^|\s)(image)(\s|$)/.test(a.className)) a.className+=" nonimage";
a.wikipage=LinkClassifier.getPageName(a.href);
if(a.wikipage==self || a.wikipage==self2) a.wikipage='';
a.origwikipage=a.wikipage;
return a.wikipage;
}).sort().filter(function(e,i,a){
return e!=='' && (i==0 || a[i-1]!==e);
});
function processLinksWithSlowdown(limit){
var props = [];
for ( var k in LinkClassifier.props ) {
props.push( k );
}
if ( a.length == 0 ) {
// This is where we detect linklessness for completely empty pages (0byte wikitext).
// This isn't a fatal error, so call the chained function in addition to removing the safety timeout
LinkClassifier.forceCallChainedFunc( );
}
function sendABatch( za, zlimit, zprops ) {
if ( za.length == 0 ) {
LinkClassifier.forceCallChainedFunc( );
return;
}
var nexta = za;
var curra = nexta.splice(0,zlimit);
LinkClassifierApiRequestsOutstanding++;
var q={
format:'json',
action:'query',
titles:curra.join('|'),
prop:'categories|pageprop|info|flagged',
redirects:1,
cllimit:'max',
inprop:'protection',
rawcontinue:1
};
if ( zprops.length <= zlimit ) {
q.ppprop = props.join( '|' );
}
$.ajax({
url:mw.util.wikiScript('api'),
dataType:'json',
type:'POST',
data:q,
rawdata:q,
success:LinkClassifier.callback,
error:function(xhr,textStatus,errorThrown){
LinkClassifier.removeUnloadHandlerIfNeeded( );
if ( typeof window.LinkClassifierStatusSel == 'string' ) {
var statusElement = $( window.LinkClassifierStatusSel );
statusElement.removeClass( 'linkclassifier-started' );
statusElement.addClass( 'linkclassifier-aborted' );
}
var errTxt = 'AJAX error (pLWS), with '
+ LinkClassifierApiRequestsOutstanding + ' requests in progress: '+textStatus+' '+errorThrown;
mw.util.jsMessage( window.LinkClassifierErrMsgPrefix + errTxt );
throw new Error( errTxt );
},
complete:LinkClassifier.maybeCallChainedFunc
});
setTimeout( sendABatch, window.LinkClassifierSlowDown, nexta, zlimit, zprops );
}
sendABatch( a, limit, props );
}
function processLinksWithoutSlowdown(limit){
var props = [];
for ( var k in LinkClassifier.props ) {
props.push( k );
}
if ( a.length == 0 ) {
// This is where we detect linklessness for completely empty pages (0byte wikitext).
// This isn't a fatal error, so call the chained function in addition to removing the safety timeout
LinkClassifier.forceCallChainedFunc( );
}
while(a.length>0){
LinkClassifierApiRequestsOutstanding++;
var q={
format:'json',
action:'query',
titles:a.splice(0,limit).join('|'),
prop:'categories|pageprop|info|flagged',
redirects:1,
cllimit:'max',
inprop:'protection',
rawcontinue:1
};
if ( props.length <= limit ) {
q.ppprop = props.join( '|' );
}
$.ajax({
url:mw.util.wikiScript('api'),
dataType:'json',
type:'POST',
data:q,
rawdata:q,
success:LinkClassifier.callback,
error:function(xhr,textStatus,errorThrown){
LinkClassifier.removeUnloadHandlerIfNeeded( );
if ( typeof window.LinkClassifierStatusSel == 'string' ) {
var statusElement = $( window.LinkClassifierStatusSel );
statusElement.removeClass( 'linkclassifier-started' );
statusElement.addClass( 'linkclassifier-aborted' );
}
var errTxt = 'AJAX error (pLWOS), with '
+ LinkClassifierApiRequestsOutstanding + ' requests in progress: '+textStatus+' '+errorThrown;
mw.util.jsMessage( window.LinkClassifierErrMsgPrefix + errTxt );
throw new Error( errTxt );
},
complete:LinkClassifier.maybeCallChainedFunc
});
}
}
function processLinks(limit){
if ( typeof window.LinkClassifierSlowDown == 'number'
&& window.LinkClassifierSlowDown == Math.ceil( window.LinkClassifierSlowDown )
&& window.LinkClassifierSlowDown > 0 ) {
processLinksWithSlowdown( limit );
}
else {
processLinksWithoutSlowdown( limit );
}
}
if( (window.LinkClassifierNoApihighlimits === true) || a.length<=100){
// Not worth querying the API to see if the user has apihighlimits
// (or user has manually declared that they lack the right)
processLinks(50);
} else {
// Note mw.user.getRights queries the API
mw.user.getRights(function(rights){
processLinks( (rights.indexOf('apihighlimits')>=0) ? 500 : 50 );
});
}
});
},
onLoad:function(){
if(window.LinkClassifierOnDemand === true) return;
if(window.AJAXPreview) window.AJAXPreview.AddOnLoadHook(LinkClassifier.classifyChildren);
LinkClassifier.onDemand();
},
onDemand:function(){
LinkClassifierChainedFuncCalledAlready = false; // belongs at the top of classifyChildren or perhaps processLinks?
LinkClassifierApiRequestsOutstanding = 0;
var node=document.getElementById('wikiPreview');
if(!node) node=document.getElementById('bodyContent');
if(node) {
LinkClassifier.initUnloadHandlerIfNeeded();
LinkClassifier.classifyChildren(node);
}
if ( window.LinkClassifierOnDemand === true ) {
var myPortletLink = $('#ca-linkclassifier');
if ( myPortletLink ) myPortletLink.remove( );
}
}
};
$(document).ready(function(){
if( window.LinkClassifierOnDemand === true ) {
mw.util.addPortletLink(defaultPref( window.LinkClassifierOnDemandLoc, 'p-cactions' ), 'javascript:LinkClassifier.onDemand()', defaultPref( window.LinkClassifierOnDemandText, 'linkclassifier' ), 'ca-linkclassifier');
}
else {
LinkClassifier.onLoad( );
}
});