User:Suffusion of Yellow/filterDiff.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.
/*
 * filterDiff: Adds a "show changes" button to the filter editor.
 * Also warns about edit conflicts.
 */
// <nowiki>
// jshint esnext: false, esversion: 8
(function() {
	/* globals $, mw, OO */
	'use strict';

	let filterId = null;

	function makeWindow(title, $content) {
		$content.dialog({
			width: 	mw.util.$content.width() * 0.75,
			height: window.innerHeight * 0.65,
			title: title
		});
	}

	function normEnds(str) {
		return str.replace(/\r\n/g, '\n').replace(/\n*$/, '');
	}

	async function showChanges() {
		let $div = $('<div></div>');

		let response = await (new mw.Api()).get({
			action: "query",
			list: "abusefilters",
			abfstartid: filterId,
			abflimit: 1,
			abfprop: "pattern"
		}).catch(() => null);

		let oldPattern, curPattern, newPattern;

		try {
			let dump = JSON.parse($('#mw-abusefilter-export textarea').val());
			oldPattern = normEnds(dump.data.rules);
			curPattern = normEnds(response.query.abusefilters[0].pattern);
			newPattern = normEnds($('#wpFilterRules').val());
		} catch(e) {
			mw.notify("filterDiff: Incomplete response from API or missing DOM element.");
			return;
		}

		if (curPattern !== oldPattern) {
			$div.append($('<div></div>', {
				style: "font-size: 125%; font-color: black; background: #FB6;",
				text: "Someone else has modified the pattern! Your changes will overwrite theirs."
			}));
		}

		if (newPattern === curPattern) {
			$div.append($('<div></div>', {
				style: "font-size: 125%; font-color: black; text-align: center;",
				text: "(pattern unchanged)"
			}));
		} else {
			let r = await (new mw.Api()).post({
				action: "compare",
				fromslots: "main",
				toslots: "main",
				"fromtext-main" : curPattern,
				"totext-main" : newPattern
			}).catch(() => null);

			try {
				$div.append('<table class="diff diff-contentalign-left diff-editfont-monospace"><colgroup><col class="diff-marker"><col class="diff-content"><col class="diff-marker"><col class="diff-content"></colgroup><tbody>' + r.compare["*"] + '</tbody></table></div>' );
			} catch (e) {
				mw.notify("filterDiff: Incomplete response from API");

				return;
			}
		}

		makeWindow("Difference between patterns", $div);
	}

	function addButtons() {
		filterId = mw.config.get('wgPageName').match(/(?:history)?\/([0-9]+)/);

		if (!filterId || !$("#mw-abusefilter-editing-form").length)
			return;

		filterId = filterId[1];

		let diffButton = new OO.ui.ButtonWidget({
			id: "efb-show-changes",
			label: "Show changes",
			title: "Compare your version of the pattern with the version currently in the database"
		});

		diffButton.on('click', showChanges);

		$('#mw-abusefilter-syntaxcheck').after(diffButton.$element);

		/* Prevent buttons from shifting when "Check syntax" is clicked */
		mw.util.addCSS(".mw-spinner { display: none; } ");
	}

	if (mw.config.get('wgCanonicalSpecialPageName') == "AbuseFilter")
		$.when($.ready,
			   mw.loader.using(['mediawiki.util',
								'mediawiki.api',
								'mediawiki.diff.styles',
								'oojs-ui',
								'jquery.ui',])).then(addButtons);
})();
//</nowiki>