User:Inductiveload/scan transcludes.js

// ================================================================== // Scan an Index page's childen for transclusion status // // Add a tool to the sidebar on Index pages. When activated, each page in the // page list is checked for transclusion. // // If pages are: //     - transcluded, they are outlined in GREEN //     - expected to be so, but are not, they are outlined in heavy RED //     - not expected to be so, and are not, they are outlined in ORANGE // // A page is "expected" to transcluded when it is proofread, validated or // prolematic, // // Multiple transclusions of the same page result in a thicker outline. // ==================================================================

/* eslint-disable one-var, vars-on-top */

( function ( $, mw ) {

'use strict';

if ( mw.config.get( 'wgCanonicalNamespace' ) !== 'Index' ) { return; }

var ST = { styles: { ok: 'outline: 1px solid green;', multiple: 'outline: 2px solid green;', expNot: 'outline: 1px solid orange;', warn: 'outline: 2px solid red;' },		exemptCats: [ 'Category:Not transcluded' ] };

var ScanTranscludes = function { this.pagelinkSelector = '.prp-index-pagelist > a'; };

ScanTranscludes.prototype.init = function {

// console.log("Init ScanTranscludes");

// only init in the index namespace if ( mw.config.get( 'wgNamespaceNumber' ) !== 106 ||				mw.config.get( 'wgAction' ) !== 'view' ) { return; }

this.installPortlet; };

ScanTranscludes.prototype.installPortlet = function {

var self = this,

// var accessKey = "a"; // self.steal_accesskey(accessKey);

portlet = mw.util.addPortletLink(				'p-tb',				'#',				'Check transclusion',				't-check-transcludes',				'Check page transclusion status (shift-click to clear)'			// accessKey			);

$( portlet ).on( 'click', function ( e ) {			e.preventDefault;

if ( e.shiftKey ) { self.clearMarking; } else { self.activate; }		} );	};

ScanTranscludes.prototype.activate = function { // console.log("Checking transclusion");

var self = this,

// inject style rules $style = $( ' ' );

for ( var key in ST.styles ) { $style.append( '._chk_trans_' + key + ' { ' + ST.styles[ key ] + '}\n' ); }

// eslint-disable-next-line no-jquery/no-global-selector $( 'html > head' ).append( $style );

$( this.pagelinkSelector ).each( function ( index, link ) {			self.processPageLink( $( link ) );		} ); };

/**	 * Gets the Page title from a link *	 * @param {jQuery} $link * @return {string} title */	function getTitleFromLink( $link ) { var title = $link.attr( 'title' );

if ( !title ) { return null; }

return title.replace( / \(.*?\)$/, '' ); }

/*	 * Consider problematic, proofread and validated as "should be transcluded" */	function linkShouldBeTranscluded( link ) { return link.hasClass( 'quality2' ) || link.hasClass( 'quality3' ) || link.hasClass( 'quality4' ); }

ScanTranscludes.prototype.processPageLink = function ( link ) { var self = this,

title = getTitleFromLink( link );

// couldn't get a link target if ( !title ) { return; }

// NOTE: for some reason _every_ page is seen as included on the Index // page. Only count transcludes from mainspace. new mw.Api.get( {			action: 'query',			list: 'embeddedin',			titles: title,			prop: 'categories',			einamespace: 0,			eititle: title,			format: 'json',			formatversion: 2		} ) .then( function ( data ) {				var count = data.query.embeddedin.length;

// list of cats in the page var cats = data.query.pages[ 0 ].categories.map( function ( pcat ) {					return pcat.title;				} );

// any excluded? var intersection = ST.exemptCats.filter( function ( exemptCat ) {					return cats.indexOf( exemptCat ) !== -1;				} );

self.decorateLink( link, count, intersection.length > 0 );

link.data( 'trans_count', count ); } );	};

ScanTranscludes.prototype.decorateLink = function ( link, count, exempt ) {

var classname = '', should = !exempt && linkShouldBeTranscluded( link );

if ( should ) { // red is not, green if yes if ( count === 0 ) { classname = 'warn'; } else { classname = ( count > 1 ) ? 'multiple' : 'ok'; }		} else { // orange if not, green if yes classname = ( count > 1 ) ? 'ok' : 'expNot'; }

// eslint-disable-next-line mediawiki/class-doc link.addClass( '_chk_trans_' + classname ); };

ScanTranscludes.prototype.clearMarking = function { for ( var key in ST.styles ) { // eslint-disable-next-line mediawiki/class-doc $( this.pagelinkSelector ).removeClass( '._chk_trans_' + key ); }	};

var st = new ScanTranscludes; st.init;

// eslint-disable-next-line no-undef }( jQuery, mediaWiki ) );