Jump to content

User:Slowking Man/scripts/ReallyComplete.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.
// <syntaxhighlight lang="javascript">
// <nowiki>

// LICENSE: CC0

// ES6-ified for great justice
// MW requires ES6 these days or else disables JS

$( () =>
{ // when whole thing wrapped in a func I figure why stuff it full of extraneous whitesp 

'use strict';

const whoami = 'AutoEd/ReallyComplete.js';

const writeToLog = ( type = 'warn' , ...args ) =>
{
	const logFn = mw.log[ type ];
	logFn( `In ${whoami}:/n` , args );
};

const errLog = ( ...x ) => writeToLog( 'error' , x );
const warnLog = ( ...x ) => writeToLog( 'warn' , x );

try {

const reqMods = 'jquery.textSelection' ,
	myloader = async mods => await mw.loader.using( mods );

myloader( reqMods );

const baseurl = '//wiki.riteme.site/w/index.php?action=raw&\
ctype=text/javascript&';

const AutoEdModule = class
{
// this is ES2022 stuff but hopefully no one trying to use with old browser
// that's why WP's builtin JS editor doesn't grok it,
// its definitions are out of date

	static #loadFn = mw.loader.load;
	static #baseAutoEd = 'title=Wikipedia:AutoEd/';
	static #core = 'core.js';
	
	static get baseAutoEd() { return this.#baseAutoEd; }
	
	#name;
	#url;
	#entryPt; // pre-emptive forward-compatibility
	#myWin; // you'll see in second
	
	get name() { return this.#name; }

	get url() { return this.#url ?? 
		AutoEdModule.#assembleUrl( this.#name ); }

	get entryPt()
	{
		return this.#entryPt ?? 
			myWin[ 'autoEd' + this.#name ];
	} // get entryPt()
	
// think of above as a modern eval()
// which is Considered Harmful for numerous reasons
// did you know calling it can make many JS engine optimizations impossible
// it can produce "self-modifying code",
// which violates many assumptions relied upon by compilers to optimize code
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval

// If you have no idea what is going on here:
// when running in "Web context", globals are defined on the global Window object
// so by default (when #entryPt undef)
// this assumes the module's entry func is "the usual"
// and returns the global entry pt func the module defined
// accessing it from global window w/ property accessor syntax
// as a computed property - computed from module name & usual name prefix (*whew*)

// You know good ol' console.log, window.close & friends
// Those are just methods, defined on those global console/window/etc objs
// you can even redefine them if you want
// disclaimer you are responsible for any Fun Stuff that happens as result
// (you are accessing them w/ "dot syntax", see also eg this.myCoolFunc();)
// in JS Everything Is An Object(tm) (terms & conditions apply)
	
// more forward-compat, when not running in something like browser (Node.js anyone?)
// there may be no global window defined
// this way if run under smth else it can pass in own "window" if it wants
// (or just define global one)
	
	get myWin()
	{ return this.#myWin ??
		window?.window; }
	
// ?. = "optional chaining" it's . but returns undef if left side is undef
// if you do foo.bar and foo is undef it throws exception
// (for ex consumer of class might want to chk value and branch based on if defined)
	
// helper method
	static #assembleUrl( modName )
	{ return baseurl + this.baseAutoEd + modName.toLowerCase() +
		modName.includes('.') ? '' : '.js'; }
// appends .js if no file extension
	
	static #load( ...mods )
	{ mods.forEach( curItem => this.#loadFn( 
		this.#assembleUrl( curItem.name ) ) ); }
	
	// come on you know I was gonna give all these features a workout :)
	// static initializer block
	// runs once, when class is well, "initialized" by JS engine
	// so let's load core here now watch this
	static
	{ this.#load( this.#core ); }
	
// rest parameter syntax
	constructor( ...args )
	{
	// and, array unpacking, together quite powerful and handy!
	// "don't repeat yourself"
		[ this.#name ,
		this.#url ,
		this.#entryPt ,
		this.#myWin , ] = args;
	} // constructor
} ; // AutoEdModule

const AutoEdMods = [ 'Unicodify' ,
'ISBN' ,
'Whitespace' ,
'UnicodeHex' ,
'Wikilinks' ,
'HTMLtoWikitext' ,
'Headlines' ,
'UnicodeControlChars' ,
'Templates' ,
'TablestoWikitext' ,
'ExtraBreaks' ,
'Fullwidth' ,
'Links' ,
// [ 'CurlyFixer' , '/* todo */' ] ,
];
// trailing , is legal & ignored, helpful lil trick to reduce forgetfulness errs

// entry pt func to be installed
const edFunc = ( mods = AutoEdMods ) =>
{
try {
// turn mod list array into array of objects
// yep another arrow func, very common ES6+ idiom
// which is why the syntax is defined that way, to cut down on boilerplate
	mods = Array.from( mods, x => new AutoEdModule(x) );
	
	const $textbox = $( '#wpTextbox1' ) , 
		ts = $textbox.textSelection;
	
	let txt = ts( 'getContents' );
	for( const curMod of mods ) { txt = curMod.entryPt( txt ); }
	ts( 'setContents' , txt );
	
// see isn't that nice and compact
	} // edFunc try
catch( e )
{ errLog( e ); }

return;
}; // edfunc

// install global func
// note: this assumes install on global window
window.autoEdFunctions = edFunc;

} // try
catch( e )
{ errLog( e ); }

return;
} ); // $( () => {

// </nowiki>
// </syntaxhighlight>