MediaWiki:Gadget-find-archived-section.js

/** _____________________________________________________________________________ * |                                                                             | * |                    === WARNING: GLOBAL GADGET FILE ===                      | * |                 Changes to this page affect many users. | * | Please discuss changes on the talk page or on FT: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 var msg = { "starter-text": "Looks like the discussion \"$1\" has been archived. ", "finding": "Finding archived discussion...", "click-link": "Click to see archived discussion", "no-search-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.", "search-link-found": "(or search in archives)", // link to search results when an exact match was obtained. "search-link-notfound": "Click to search in archives" // link to search results when an exact match was NOT obtained. }; 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 "FAMEPedia:Administrators' noticeboard/Incidents": return "FAMEPedia:Administrators' noticeboard/IncidentArchive"; case "FAMEPedia:Administrators' noticeboard/Edit warring": return "FAMEPedia:Administrators' noticeboard/3RRArchive"; case "FAMEPedia:Administrators' noticeboard": return "FAMEPedia:Administrators' noticeboard/Archive"; 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 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		document.getElementById(sectionName.replace(/ /g, '_')) !== null) { // section exists on page return; }	var sanitiseString = function(str, escapeHtml) { // if str contains $ signs, we don't want String.prototype.replace to treat them with special meaning return (escapeHtml ? mw.html.escape(str) : str).replace(/\$/g, '$$$$'); };

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

$('#mw-content-text').before(		$(' ')			.text(msg['starter-text'].replace('$1', sanitiseString(sectionName, false)) + msg['finding'])			.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 divHtml; var results = json.query.search; if (results.length === 0) { divHtml = msg['no-search-results'].replace('$1', sanitiseString(sectionName, true));

} 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 var sectionName_ = sectionName.replace(/ /g, '_'); var sectionNameDotDecoded_ = sectionNameDotDecoded.replace(/ /g, '_'); for (var i in results) { var result = results[i]; // sectiontitle in API output has spaces encoded as underscores if (result.sectiontitle) { if (result.sectiontitle === sectionName_ ||						result.sectiontitle === sectionNameDotDecoded_) {

pageTitle = result.title; sectionNameFound = result.sectiontitle.replace(/_/g, ' '); 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'			});

divHtml = msg['starter-text'].replace('$1', sanitiseString(sectionNameFound || sectionName, true));

if (pageTitle) { // if a section with the same name was found var discussionLink = mw.util.getUrl(pageTitle) + '#' + mw.util.wikiUrlencode(sectionNameFound); divHtml += '' + msg['click-link'] + ' '; divHtml += ' ' + msg['search-link-found'] + '. ';

} else { divHtml += '' + msg['search-link-notfound'] + '. ';			}		}

$('.archived-section-prompt').html(divHtml);

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

});