User:Fred Gandt/fixDodgyShortDescriptions.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.
$( document ).ready( () => {
	"use strict";
	const api = ( data, fnc ) => {
		data.format = "json";
		$.ajax( {
			type: "POST",
			url: "/w/api.php",
			dataType: data.format,
			data: data,
			success: data => fnc( data ),
			error: data => console.error( data )
		} );
	},
	api_getContent = ( title, fnc ) => {
		api( {
			action: "query",
			prop: "revisions",
			titles: title,
			formatversion: "2",
			rvprop: "content",
			rvslots: "*",
			token: mw.user.tokens.values.csrfToken
		}, fnc );
	},
	api_editContent = ( title, text, summary, minor, form ) => {
		const REQUEST = {
			action: "edit",
			title: title,
			text: text,
			contentformat: "text/x-wiki",
			contentmodel: "wikitext",
			summary: summary,
			token: mw.user.tokens.values.csrfToken
		};
		if ( minor ) {
			REQUEST.minor = "1";
		}
		api( REQUEST, data => {
			if ( data.edit && data.edit.result === "Success" ) {
				mw.notify( `Edit to ${title} successful`, { tag: "fixDodgyShortDescriptions", type: "success" } );
			} else {
				mw.notify( `Edit to ${title} might have failed`, { tag: "fixDodgyShortDescriptions", type: "error" } );
			}
			form.remove();
		} );
	},
	giveForm = ( title, content, sd_content ) => {
		const FORM = document.createElement( "form" ),
			TITLE = document.createElement( "h3" ),
			SHORT_DESC = document.createElement( "p" ),
			TEXTAREA = document.createElement( "textarea" ),
			SUMMARY = document.createElement( "input" ),
			SUMMARY_PRESETS = document.createElement( "select" ),
			MINOR = document.createElement( "input" ),
			SUBMIT = document.createElement( "input" ),
			CANCEL = document.createElement( "input" );
		TITLE.textContent = title;
		SHORT_DESC.textContent = sd_content;
		SUMMARY.type = "text";
		TEXTAREA.value = content;
		[ "replaced uncommon whitespace characters in {{Short description}} with common spaces",
			"{{Short description|none}} self describing title [[WP:SDNONE]]; [[WP:SDNOTDEF]]",
			"{{Short description|}} -> {{Short description|}} [[WP:SDNOTDEF]]",
			"[[MOS:DATERANGE]] in {{Short description}} –",
			"[[MOS:CURLY]] in {{Short description}}"
		].forEach( option => {
			const OPTION = document.createElement( "option" );
			OPTION.textContent = OPTION.value = option;
			SUMMARY_PRESETS.append( OPTION );
		} );
		SUMMARY.addEventListener( "keypress", evt => ( evt.key === "Enter" ? evt : null )?.preventDefault() );
		SUMMARY_PRESETS.addEventListener( "change", () => SUMMARY.value = SUMMARY_PRESETS.value, { passive: true } );
		SUMMARY.value = SUMMARY_PRESETS.value;
		SUBMIT.type = "button";
		SUBMIT.value = "Submit";
		CANCEL.type = "button";
		CANCEL.value = "Cancel";
		MINOR.type = "checkbox";
		MINOR.checked = true;
		FORM.id = "fg-fix-dodgy-short-descriptions";
		FORM.addEventListener( "click", evt => {
			const TARGET = evt.target;
			if ( TARGET === SUBMIT ) {
				api_editContent( title, TEXTAREA.value, SUMMARY.value, MINOR.checked, FORM );
			} else if ( TARGET === CANCEL ) {
				FORM.remove();
			}
		} );
		FORM.append( TITLE );
		FORM.append( SHORT_DESC );
		FORM.append( TEXTAREA );
		FORM.append( SUMMARY );
		FORM.append( SUMMARY_PRESETS );
		FORM.append( SUMMARY );
		FORM.append( SUBMIT );
		FORM.append( CANCEL );
		FORM.append( MINOR );
		document.body.append( FORM );
		TEXTAREA.focus();
		TEXTAREA.setSelectionRange( 20, 20 );
		TEXTAREA.scrollTo( 0, 0 );
	},
	REG_EXP = /(\{\{\s*(?:S|s)hort(?: |_)desc(?:ription)?\s*\|\s*([^}]+?)\s*\}\})/;
	
	if ( mw.config.get( "wgPageName" ) == "Special:Search" ) {
		const SEARCH_RESULTS = document.querySelector( ".mw-search-results" );
		if ( SEARCH_RESULTS && SEARCH_RESULTS.querySelectorAll( ".mw-search-result" ).length ) {
			const STYLE_SHEET = new CSSStyleSheet();
			document.adoptedStyleSheets = [ ...document.adoptedStyleSheets, STYLE_SHEET ];
			STYLE_SHEET.replaceSync( `#fg-fix-dodgy-short-descriptions {
	box-shadow: 0 0 1em #00000080;
	background-color: #ffffff;
	border: 1px solid #a7d7f9;
	position: fixed;
	padding: 1em;
	z-index: 100;
	width: 60vw;
	left: 20vw;
	top: 20vh;
}
#fg-fix-dodgy-short-descriptions textarea {
	resize: vertical;
	height: 4em;
}
#fg-fix-dodgy-short-descriptions select {
	background-color: #dcf1ff;
	font-family: monospace;
	display: block;
}
#fg-fix-dodgy-short-descriptions input[type="text"] {
	font-family: monospace;
	display: block;
	width: 98%;
}
#fg-fix-dodgy-short-descriptions input[type="button"] {
	margin-right: .5em;
}
#fg-fix-dodgy-short-descriptions * + * {
	margin-top: .5em;
}
#fg-fix-dodgy-short-descriptions *:not( input[type="button"], h3, p ) {
	padding: .5em;
}` );
			SEARCH_RESULTS.addEventListener( "click", evt => {
				const RESULT = evt.composedPath().find( element => element.classList.contains( "mw-search-result" ) );
				if ( RESULT ) {
					const TITLE = RESULT.querySelector( ".mw-search-result-heading a" ).title;
					if ( TITLE ) {
					evt.preventDefault();
						api_getContent( TITLE, data => {
							if ( data.batchcomplete ) {
								let content = data.query.pages[ 0 ].revisions[ 0 ].slots.main.content;
								if ( content ) {
									const EXEC = REG_EXP.exec( content );
									if ( EXEC ) {
										const SD_CONTENT = EXEC[ 2 ];
										if ( SD_CONTENT ) {
											content = content.replace( REG_EXP, "" );
											giveForm( TITLE, `{{Short description|}}${content}`, SD_CONTENT );
										}
									}
								}
							}
						} );
					}
				}
			} );
		}
	}
} );