Jump to content

User:Phlsph7/MarkDuplicateLinks.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:Evad37/duplinks-alt.js]]
//This script uses material from Wikipedia user Ucucha's script "duplinks" ( https://en.wikipedia.org/wiki/User:Ucucha/duplinks.js ), which is released under the Creative Commons Attribution-Share-Alike License 3.0 ( http://creativecommons.org/licenses/by-sa/3.0/ )
//See also https://en.wikipedia.org/wiki/User:Ucucha/duplinks for documentation of the original script
$( function($) {
	var namespaceNumber = mw.config.get('wgNamespaceNumber');
	// only check links in mainspace, and userspace (for userspace drafts), and draftspace
	var isCorrectNamespace = namespaceNumber === 0 || namespaceNumber === 2 || namespaceNumber === 118;
	if (!isCorrectNamespace) {
		return;
	}
	mw.loader.using('mediawiki.util').then(function(){
		var portletlink = mw.util.addPortletLink('p-tb', '#', 'Highlight duplicate links', 'ca-findduplicatelinks');
		$(portletlink).click( function(e) {
			e.preventDefault();			
			// Check if VisualEditor is being used - the element surrounding text is different in VE
			var isVisualEditor = window.location.href.search("veaction")>0;
			// Get the element immediately surrounding the article text.
			var $content = isVisualEditor ? $(".ve-ce-documentNode.ve-ce-branchNode") : $($(".mw-parser-output", "#mw-content-text")[0])
			// Create a separate div to conatin the lead
			$lead = $("<div id='lead'>").prependTo($content);
			// Move the elements containing the lead content into this newly-created div
			$lead.nextAll().each( function() {
				if (this.nodeName.toLowerCase() == 'h2') {
					// Reached the first heading after the lead.
					// Returning false breaks out of the jQuery .each() loop early
					return false;
				}
				$lead.append(this);
				return true;
			});

			// Objects to keep track of whether we've seen a link before, and which links are duplicated
			var seen = {};
			var duplicated = {};
			var hasDuplicatedLinks = false;

			// Styles
			mw.util.addCSS(".duplicate-link { border: 1px solid red; }\n.duplicated-link { border: 1px dashed green; }");
			
			// Detect and mark links which are duplicates
			var finddups = function() {
				var href = this.attributes.href && this.attributes.href.value;
				if (href != undefined && href.indexOf('#') != 0) {
					if (seen[href]) {
						this.classList.add("duplicate-link");
						duplicated[href] = true;
						hasDuplicatedLinks = true;
					}
					else {
						seen[href] = true;
					  }
				}
				return true;
			};
			// Detect and mark the first occurance of duplicated links
			var markdups = function() {
				var href = this.attributes.href && this.attributes.href.value;
				if(href != undefined && href.indexOf('#') != 0) {
					if(duplicated[href]) {
						this.classList.add("duplicated-link");
						duplicated[href] = '';
					}
				}
				return true;
			};

			// Process sections after the lead
			mw.util.$content.find('p a').not('#lead *, .infobox *, .navbox *').each(finddups);
			mw.util.$content.find('p a').not('#lead *, .infobox *, .navbox *').each(markdups);
			
			// Reset tracking objects, process lead section
			seen = {};
			duplicated = {};
			mw.util.$content.find('#lead p a').not('.infobox *, .navbox *').each(finddups);
			mw.util.$content.find('#lead p a').not('.infobox *, .navbox *').each(markdups);

			// Show a notice if no duplicates were found
			if (!hasDuplicatedLinks) {
				mw.notify('No duplicated links were detected');
			}
		});
	});
});