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 errLog = x => mw.log.error( x );

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

const myModules = 'jquery.textSelection' ;

const myCallBack = () =>
{

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; }
	static get core() { return this.#core; }
	
	#name;
	#url;
	#entryPt; // pre-emptive forward-compatibility
	#myGlobal; // you'll see in second
	
	get name() { return this.#name; }

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

	get entryPt()
	{
		return this.#entryPt ?? 
			this.#myGlobal[ '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)
	
// ?. = "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.#myGlobal = globalThis , ] = args;
		
		new.target.load( this );
	} // 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' );
	const 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

Object.defineProperty( globalThis, 'autoEdFunctions', {
    value: edFunc,
    enumerable: false,
    configurable: true,
    writable: true,
  });

return;
}; // myCallback

// register our callback
// when executed it installs global func
mw.loader.using( myModules, myCallBack );

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

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