Jump to content

User:Mathglot/HarvErrors.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// copy of [[User:Trappist the monk/HarvErrors.js]] rev. 1171512037 of 15:14, 21 August 2023; look for '+MOD+' flags.

mw.hook( 'wikipage.content' ).add( function( $content )
	{
	mw.loader.addStyleTag ('.ttm_harv_err_dflt {color:DarkOrange}');		// +MOD+ no target error message default color
	mw.loader.addStyleTag ('.ttm_harv_err_dup {color:#C3F}');					// duplicate target error message default color (sfn or harv template – source)
	mw.loader.addStyleTag ('.ttm_err_harv_dup {color:#C3F}');					// duplicate target error message default color (citation template – target)
	mw.loader.addStyleTag ('.ttm_harv_warn {color:#ac6600}');					// warning message default color
// load User:Username/HarvErrors.css here if it exists	
	var cites = $content.find('.citation');										// get all cites on the page
	var citeref_tgt_counts = {};												// associative array of citerefs as key, their number as value
	var citeref_source_ids = {};												// associative array of citerefs from sfn, harv templates
	var idi;																	// citeref id in and iterated loop
	
	for (var i=0; i < cites.length; i++)										// fill the array; to be used when identifying multiple targets
		{
		idi = cites[i].getAttribute('id');										// get citeref anchor from cites[]
		if ((idi in citeref_tgt_counts))										// is target in the associative array
			citeref_tgt_counts[idi]++;											// yep, bump the count
		else
			citeref_tgt_counts[idi] = 1;										// nope, add it with a count of one
		}

	var href, links = $content.find( 'a[href^="#CITEREF"]' );					// make a list of harv and sfn links
		
	links.each( function (i, elem)												// first check: do links in Harvard citations point to a valid citation?
		{
		href = elem.getAttribute( 'href' ).substring(1); //skip the #
		// IDs can contain characters like . that have meaning in selectors
		// use $.escapeSelector to make sure they are escaped
		if ( $content.find( '#' + $.escapeSelector(href) ).length < 1)
			$(elem.parentNode).append(" ", $("<span class=\"ttm_harv_err ttm_harv_err_dflt\">Harv error: link from " + href + " doesn't point to any citation.</span>"));  // +MOD+ dflt and override classes
		else if (1 < citeref_tgt_counts[href])
			{
			$(elem.parentNode).append(" ", $("<span class=\"ttm_harv_err_dup\">Harv error: " + href + " has multiple targets (" + citeref_tgt_counts[href] + "×).</span>"));
			citeref_source_ids[href] = 1;										// add this citeref to the list; duplicates simply overwrite
			}
		});

	// second check: do CITEREF IDs have Harvard citations pointing to them?

	if (0 !== links.length)														// non-zero when links were found
		{
		var further_reading = $content.find('#Further_reading').parent().nextUntil('h2').find('.citation').get();	// get all cites inside a Further reading section
		var external_links = $content.find('#External_links').parent().nextUntil('h2').find('.citation').get();		// get all cites inside a External links section

		var sections = [further_reading, external_links];						// make an array of links in these sections

		var filtered_cites = cites.get().filter(function(x) { return further_reading.indexOf(x) === -1; });	// all cites not in 'Further reading' section
		filtered_cites = filtered_cites.filter(function(x) { return external_links.indexOf(x) === -1; });	// all cites not in 'External links' section
		
		var id;
		var query;

		for(i=0; i < filtered_cites.length; i++)
			{
			id = filtered_cites[i].getAttribute('id');
			// we only need to check citations with an id that is a CITEREF id
			if(!id || id.indexOf('CITEREF') !== 0)
				continue;
			// don't do cites that are inside a ref
			var parentid = filtered_cites[i].parentNode.parentNode.getAttribute('id');
			if(parentid && parentid.indexOf('cite_note') === 0)
				continue;
			// check for links to this citation
			query = 'a[href|="#' + $.escapeSelector(id) + '"]';
			if($content.find(query).length === 0)
				$(filtered_cites[i]).append(" ", $("<span class=\"ttm_harv_warn\">Harv warning: There is no link pointing to this citation. The anchor is named " + id + ".</span>"));
			}

		// third check: are Harvard citations pointing to citerefs in inappropriate article sections?
		for (var s=0; s < sections.length; s++)									// loop through the list of sections
			{
			for (i=0; i < sections[s].length; i++)								// look for linked cites in sections[s]
				{
				id = sections[s][i].getAttribute('id');
				query = 'a[href|="#' + $.escapeSelector(id) + '"]';
				if($content.find(query).length !== 0)
					$(sections[s][i]).append(" ", $("<span class=\"ttm_harv_err\">Harv error: linked from " + id + ".</span>"));
				}
			}

		// fourth check: do Harvard citations have multiple targets?
		for (i=0; i < cites.length; i++)
			{
			idi = cites[i].getAttribute('id');
			if (!(idi in citeref_source_ids))									// only check citations that have matching sfn or ref templates
				continue;
				
			if(!idi || idi.indexOf('CITEREF') !== 0)							// only check citations with an id that is a CITEREF id
				continue;

			if (1 < citeref_tgt_counts[idi])
				$(cites[i]).append(" ", $("<span class=\"ttm_err_harv_dup\">Harv error: duplicate target for " + idi + ".</span>"));
			}
		}
	});