Jump to content

User:Evad37/duplinks-alt/sandbox.js

From Wikipedia, the free encyclopedia
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.
//This script uses material from Wikipedia user Ucucha's script "duplinks" ( https://wiki.riteme.site/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://wiki.riteme.site/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.util.addCSS(".duplicate-link { border: 1px solid red; }\n.duplicated-link { border: 1px dashed green; }");
	
	var setActiveState = function (isActive) {
		try {
			localStorage.setItem('duplinks.active', isActive ? 'true' : '');
		} catch(e) {}
	};
	var getActiveState = function () {
		try {
			return !!localStorage.getItem('duplinks.active');
		} catch(e) {
			return false;
		}
	};
	
	var highlightDuplicateLinks = function() {
			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

			
			// 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);

			return hasDuplicatedLinks;
	};
	
	var unhighlightLinks = function() {
		mw.util.$content.find('p a').each(function() {
			var href = this.attributes.href && this.attributes.href.value;
				if (href != undefined && href.indexOf('#') != 0) {
					if (this.classList.contains("duplicated-link")) {
						this.classList.remove("duplicated-link");
						this.classList.add("duplicated-link-plain");
					}
					if (this.classList.contains("duplicate-link")) {
						this.classList.remove("duplicate-link");
						this.classList.add("duplicate-link-plain");
					}
				}
				return true;
		});
	};
	
	var rehighlightLinks = function() {
		mw.util.$content.find('p a').each(function() {
			var href = this.attributes.href && this.attributes.href.value;
				if (href != undefined && href.indexOf('#') != 0) {
					if (this.classList.contains("duplicated-link-plain")) {
						this.classList.remove("duplicated-link-plain");
						this.classList.add("duplicated-link");
					}
					if (this.classList.contains("duplicate-link-plain")) {
						this.classList.remove("duplicate-link-plain");
						this.classList.add("duplicate-link");
					}
				}
				return true;
		});
	};
	
	mw.loader.using('mediawiki.util').then(function(){
		var isActive = getActiveState();
		var portletlinkUnhighlight = mw.util.addPortletLink('p-tb', '#', 'Unhighlight duplicate links', 'ca-unfindduplicatelinks', null, null, null);
		var portletlinkRehighlight = mw.util.addPortletLink('p-tb', '#', 'Highlight duplicate links', 'ca-refindduplicatelinks', null, null, '#ca-unfindduplicatelinks');
		$(portletlinkRehighlight).hide();
		
		// Initial highlighting
		if (isActive) {
			highlightDuplicateLinks();
		} else {
			$(portletlinkUnhighlight).hide();
			var portletlinkHighlight = mw.util.addPortletLink('p-tb', '#', 'Highlight duplicate links', 'ca-findduplicatelinks', null, null, '#ca-unfindduplicatelinks');
			$(portletlinkHighlight).click( function(e) {
				e.preventDefault();			
				var hasDuplicatedLinks = highlightDuplicateLinks();
				setActiveState(true);
				
				// Show a notice if no duplicates were found
				if (!hasDuplicatedLinks) {
					mw.notify('No duplicated links were detected');
				}
				
				$(portletlinkHighlight).hide();
				$(portletlinkUnhighlight).show();
			});
		}
		
		// Un-highlighting
		$(portletlinkUnhighlight).click( function(e) {
			e.preventDefault();			
			unhighlightLinks();
			setActiveState(false);
			$(portletlinkUnhighlight).hide();
			$(portletlinkRehighlight).show();
		});
		
		
		// Re-highlighting
		$(portletlinkRehighlight).click( function(e) {
			e.preventDefault();			
			rehighlightLinks();
			setActiveState(true);
			$(portletlinkRehighlight).hide();
			$(portletlinkUnhighlight).show();
		});
	});
});