Jump to content

MediaWiki:Gadget-find-archived-section.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.
/**  _____________________________________________________________________________
 * |                                                                             |
 * |                    === WARNING: GLOBAL GADGET FILE ===                      |
 * |                  Changes to this page affect many users.                    |
 * | Please discuss changes on the talk page or on [[WT:Gadget]] before editing. |
 * |_____________________________________________________________________________|
 *
 * Gadget to navigate to an archived section after following its broken link.
 *
 * Author: SD0001
 * Documentation: [[User:SD0001/find-archived-section]]
 *
 */


// START EDITING HERE FOR LOCALISATION
// Messages: translate these strings if porting to a non-English language wiki
mw.messages.set({
	"fas-finding": 'Looks like the discussion "$1" has been archived. Finding archived discussion...',
	"fas-exact-match": 'Looks like the discussion "$1" has been archived. <b><a href="$2">Click to see archived discussion</a></b> <small>(<a href="$3">or search in archives</a>)</small>',
	"fas-inexact-match": 'Looks like the discussion "$1" has been archived. <a href="$2">Click to search in archives</a>.',
	"fas-no-results": 'No search results found for section "$1" in archives. It may have been removed or renamed, or you may have followed a malformed link.',
});

var config = {
	// Function to introduce arbitrary changes to prefix.
	// Used here as archive page names used for admin noticeboards on enwiki are unusual
	prefixNormaliser: function(prefix) {
		switch (prefix) {
			case "Wikipedia:Administrators' noticeboard/Incidents":
				return "Wikipedia:Administrators' noticeboard/IncidentArchive";
			case "Wikipedia:Administrators' noticeboard/Edit warring":
				return "Wikipedia:Administrators' noticeboard/3RRArchive";
			case "Wikipedia:Administrators' noticeboard":
				return "Wikipedia:Administrators' noticeboard/Archive";
			case "Wikipedia:Reference desk/Science":
				return "Wikipedia:Reference desk/Archives/Science";
			case "Wikipedia:Reference desk/Miscellaneous":
				return "Wikipedia:Reference desk/Archives/Miscellaneous";
			case "Wikipedia:Reference desk/Mathematics":
				return "Wikipedia:Reference desk/Archives/Mathematics";
			case "Wikipedia:Reference desk/Language":
				return "Wikipedia:Reference desk/Archives/Language";
			case "Wikipedia:Reference desk/Humanities":
				return "Wikipedia:Reference desk/Archives/Humanities";
			case "Wikipedia:Reference desk/Entertainment":
				return "Wikipedia:Reference desk/Archives/Entertainment";
			case "Wikipedia:Reference desk/Computing":
				return "Wikipedia:Reference desk/Archives/Computing";
			case "Wikipedia:Reference desk":
				return "Wikipedia:Reference desk/Archives";
			case "Wikipedia:Teahouse":
				return "Wikipedia:Teahouse/Questions";
			default:
				return prefix;
		}
	}
};
// STOP EDITING HERE FOR LOCALISATION

$(function() {

	var addsection = document.getElementById('ca-addsection');
	var correctNs = mw.config.get('wgNamespaceNumber') % 2 === 1 || mw.config.get('wgNamespaceNumber') === 4;
	var minerva = mw.config.get('skin') === 'minerva';

	// Show only on discussion pages (pages with "add section" button)
	// On minerva skin (which doesn't use the add section button) show on all talk & project space pages
	if (!addsection && (!correctNs || !minerva)) {
		return;
	}

	var sectionName = decodeURIComponent(
		window.location.hash.slice(1)  // to remove the leading #
			.replace(/_/g, ' ')
	);

	// For anchor-encoded (UTF-8 percent encoding but with % replaced by a period (.) ), try to undo the encoding.
	// For some strange reason, MediaWiki doesn't encode . itself, because of this the encoding process isn't
	// exactly reversible. But this should work for the vast majority of cases.
	var sectionNameDotDecoded = decodeURIComponent(sectionName.replace(/\.([0-9A-F]{2})/g, '%$1'));

	if (!sectionName || // no section name in URL
		sectionName.indexOf('/media/') === 0 || // URLs used by MediaViewer
		/^c-/.test(sectionName) || //URLs used by DiscussionTools
		/^\d{12} /.test(sectionName) || // URLs used by convenientDiscussions
		/^noticeApplied-/.test(sectionName) || // URLs used by RedWarn
		document.getElementById(sectionName.replace(/ /g, '_')) !== null) { // section exists on page
		return;
	}

	var escapeQuotes = function(str) {
		return str.replace(/"/g, '\\"');
	};

	$('#mw-content-text').before(
		$('<div>')
			.text(mw.msg('fas-finding', sectionName))
			.addClass('archived-section-prompt')
			.css({
				'font-size': '90%',
				'padding': '0 0 10px 20px'
			})
	);

	var prefix = mw.config.get('wgPageName').replace(/_/g, ' ');

	// Apply normalisation for for admin noticeboards
	if (typeof config.prefixNormaliser === 'function') {
		prefix = config.prefixNormaliser(prefix);
	}

	var searchQuery = sectionNameDotDecoded === sectionName ?
		'"' + escapeQuotes(sectionName) + '" prefix:"' + prefix + '"' :
		'"' + escapeQuotes(sectionName) + '" OR "' + escapeQuotes(sectionNameDotDecoded) + '" prefix:"' + prefix + '"';

	mw.loader.using(['mediawiki.util', 'mediawiki.api']).then(function() {

		return new mw.Api({
			ajax: { headers: { 'Api-User-Agent': 'w:en:MediaWiki:Gadget-find-archived-section.js' } }
		}).get({
			action: 'query',
			list: 'search',
			srsearch: searchQuery,
			srprop: 'sectiontitle',
			srsort: 'create_timestamp_desc', // list more recent archives first
			srlimit: '20'
		});

	}).then(function(json) {
		if (!json || !json.query || !json.query.search) {
			return;
		}

		var results = json.query.search;
		if (results.length === 0) {
			$('.archived-section-prompt').html(mw.msg('fas-no-results', mw.html.escape(sectionName)));

		} else {
			var pageTitle,
				sectionNameFound; // will either be sectionName or sectionNameDotDecoded

			// obtain the the first exact section title match (which would be from the most recent archive)
			// this loop iterates over just one item in the vast majority of cases
			for (var i in results) {
				var result = results[i];
				if (
					result.sectiontitle &&
					(result.sectiontitle === sectionName || result.sectiontitle === sectionNameDotDecoded)
				) {
					pageTitle = result.title;
					sectionNameFound = result.sectiontitle;
					break;
				}
			}

			var searchLink = mw.util.getUrl('Special:Search', {
				search: '~' + searchQuery, // ~ in the beginning forces a search even if a page of the same name exists, see [[H:FORCE]]
				prefix: prefix,
				sort: 'create_timestamp_desc'
			});

			var escapedSectionName = mw.html.escape(sectionNameFound || sectionName);

			if (pageTitle) { // if a section with the same name was found
				var discussionLink = mw.util.getUrl(pageTitle) + '#' + mw.util.wikiUrlencode(sectionNameFound);
				$('.archived-section-prompt').html(mw.msg('fas-exact-match', escapedSectionName, discussionLink, searchLink));
			} else {
				$('.archived-section-prompt').html(mw.msg('fas-inexact-match', escapedSectionName, searchLink));
			}
		}

	}).catch(function(err) {
		console.error('[find-archived-section]: ', JSON.stringify(err));
	});

});