User:HouseBlaster/HighlightCFD.js

/* Personal fork of User:Anomie/linkclassifier.js, which only loads for CFDs. Just to make sure things were tagged properly before I set the bot loose on 'em */

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: { houseblasterdeletion: [ 'Category:All categories for discussion', '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', ].sort, houseblasteremptycategory: [ 'Category:Empty categories awaiting deletion' ]	},

/* Was it run already? */	wasRun: false,

onAjaxError: function ( xhr, textStatus, errorThrown ) { mw.log.error( 'AJAX error: ' + textStatus + ' ' + errorThrown ); },

callback: function ( r ) { var i, j, k, k2, v, node, alist, q, prefix, seen, cls, redirlist = [], cats = {}, missing = {}, classes = {};

if ( !r || !r.query ) { if ( !window.console || !$.isFunction( window.console.error ) ) { throw new Error( 'Bad response' ); }			window.console.error( 'Bad response', r ); return; }		if ( r['query-continue'] ) { q = this.rawdata; for ( k in r['query-continue'] ) { for ( k2 in r['query-continue'][k] ) { q[k2] = r['query-continue'][k][k2]; }			}			$.ajax( {				url: mw.util.wikiScript( 'api' ),				dataType: 'json',				type: 'POST',				data: q,				rawdata: this.rawdata,				success: LinkClassifier.callback,				error: LinkClassifier.onAjaxError			} ); }		r = r.query;

node = document.getElementById( 'wikiPreview' ); if ( !node ) { node = document.getElementById( 'bodyContent' ); }		if ( !node ) { throw new Error( 'Huh? No body content?' ); }		alist = node.getElementsByTagName( 'A' ); if ( alist.length === 0 ) { return; }

prefix = this.rawdata.redirects ? '' : 'redir-'; if ( r.pages ) { for ( i in r.pages ) { classes[r.pages[i].title] = []; missing[r.pages[i].title] = r.pages[i].missing !== undefined; if ( r.pages[i].categories ) { cats[r.pages[i].title] = r.pages[i].categories.map( function ( a ) {						return a.title;					} ).sort; }			}		}		Array.prototype.forEach.call( alist, function ( a ) {			var cns, cls, m, i, j, pageCats, matchCats,				$a = $( a );

if ( a.wikipage === undefined ) { return; }			m = a.href.match( /#.*/ ); if ( m && m[0].substr( 0, 10 ) !== '#cite_note' ) { try { // Modern MediaWiki doesn't normally do the dot-encoding thing anymore, but humans/scripts sometimes still do. a.title = a.title.replace( /#.*/, '' ) + decodeURIComponent( m[0].replace( /_/g, ' ' ).replace( /\.([0-9A-F][0-9A-F])/g, '%$1' ) ); } catch ( e ) { // Malformed UTF8? Decode it as bytes. a.title = a.title.replace( /#.*/, '' ) + m[0].replace( /_/g, ' ' ).replace( /\.([0-9A-F][0-9A-F])/g, function ( x, n ) {						return String.fromCharCode( parseInt( n, 16 ) );					} ); }			}			if ( classes[a.wikipage] ) { for ( j = classes[a.wikipage].length - 1; j >= 0; j-- ) { $a.addClass( classes[a.wikipage][j] ); }			}

pageCats = []; if ( cats[a.wikipage] ) { pageCats = pageCats.concat( cats[a.wikipage] ); }			if ( pageCats.length > 0 ) { pageCats = pageCats.sort; for ( cls in LinkClassifier.cats ) { i = pageCats.length - 1; matchCats = LinkClassifier.cats[cls]; if ( matchCats instanceof RegExp ) { while ( i >= 0 ) { if ( matchCats.test( pageCats[i] ) ) { $a.addClass( cls ); break; }							i--; }					} else { j = matchCats.length - 1; while ( i >= 0 && j >= 0 ) { if ( pageCats[i] === matchCats[j] ) { $a.addClass( cls ); break; }							if ( pageCats[i] > matchCats[j] ) { --i; } else { --j; }						}					}				}			}		} );	},

draftsCallback: function ( r ) { var i, node, alist, found = {};

if ( !r.query ) { if ( !window.console || !$.isFunction( window.console.error ) ) { throw new Error( 'Bad response' ); }			window.console.error( 'Bad response', r ); return; }		r = r.query;

node = document.getElementById( 'wikiPreview' ); if ( !node ) { node = document.getElementById( 'bodyContent' ); }		if ( !node ) { throw new Error( 'Huh? No body content?' ); }		alist = node.getElementsByTagName( 'A' ); if ( alist.length === 0 ) { return; }

if ( r.pages ) { for ( i in r.pages ) { found[r.pages[i].title] = r.pages[i].missing === undefined; }		}	},

getPageName: function ( url ) { var t, m = url.match( /\/wiki\/([^?#]+)/ ); if ( !m ) { m = url.match( /\/w\/index.php\?(?:.*&)?title=([^&#]+)/ ); }		if ( !m ) { return ''; }		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 alist, titles, draftTitles, re, self, i, k;

LinkClassifier.wasRun = true; alist = node.getElementsByTagName( 'A' ); if ( !alist.length ) { return; }			self = LinkClassifier.getPageName( location.href ); titles = Array.prototype.map.call( alist, function ( a ) {				a.wikipage = ;				if ( /(^|\s)(external|extiw)(\s|$)/.test( a.className ) ) {					return ;				}				if ( !/(^|\s)(image|mw-file-description)(\s|$)/.test( a.className ) ) {					a.className += ' nonimage';				}				a.wikipage = LinkClassifier.getPageName( a.href );				if ( a.wikipage === self ) {					a.wikipage = ;				}				return a.wikipage;			} ).sort.filter( function ( e, i, a ) {				return e !==  && ( i === 0 || a[i - 1] !== e );			} );

re = []; for ( k in mw.config.get( 'wgNamespaceIds' ) ) { if ( k !== '' ) { re.push( k.replace( /_/g, ' ' ) ); }			}			re = new RegExp( '^(' + re.join( '|' ) + '):', 'i' );

function processLinks( limit ) { var q;				while ( titles.length > 0 ) { q = { format: 'json', action: 'query', titles: titles.splice( 0, limit ).join( '|' ), prop: 'categories', redirects: 1, cllimit: 'max', rawcontinue: 1 };					$.ajax( {						url: mw.util.wikiScript( 'api' ),						dataType: 'json',						type: 'POST',						data: q,						rawdata: q,						success: LinkClassifier.callback,						error: LinkClassifier.onAjaxError					} ); }			}

if ( titles.length <= 100 ) { // Not worth querying the API to see if the user has apihighlimits 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.AJAXPreview ) { window.AJAXPreview.AddOnLoadHook( LinkClassifier.classifyChildren ); }		LinkClassifier.onDemand; },

onDemand: function { mw.hook( 'LinkClassifier' ).fire( this ); var node = document.getElementById( 'wikiPreview' ); if ( !node ) { node = document.getElementById( 'bodyContent' ); }		if ( node ) { LinkClassifier.classifyChildren( node ); }	},

rerun: function { if ( LinkClassifier.wasRun ) { LinkClassifier.onDemand; }	} };

$( document ).ready( LinkClassifier.onLoad );