MediaWiki:Gadget-EoMagicalConversion.js

From Wikipedia

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/*
 * This script emulates MediaWiki's implementation of Esperanto X-coding.
 * For more information, see [[w:Esperanto orthography#X-system]] and 
 * [[svn:trunk/phase3/languages/classes/LanguageEo.php]].
 */

/*global mw:false, jQuery:false*/
/*jshint curly:false*/

function esperantoHandlers() {
'use strict';
	var $ = jQuery;
	var decMap = {
		'C': 'Ĉ', 'c': 'ĉ',
		'G': 'Ĝ', 'g': 'ĝ',
		'H': 'Ĥ', 'h': 'ĥ',
		'J': 'Ĵ', 'j': 'ĵ',
		'S': 'Ŝ', 's': 'ŝ',
		'U': 'Ŭ', 'u': 'ŭ'};

	var encMap = {};
	for (var c in decMap) {
		if (decMap.hasOwnProperty(c)) {
			encMap[decMap[c]] = c + "x";
		}
	}

	function xEncode (str) {
		// XXX: use a look-ahead assertion to avoid problems with capturing parens in split() on IE
		var chunks = str.split( /(?=[CcGgHhJjSsUu][Xx]|[ĈĉĜĝĤĥĴĵŜŝŬŭ])/ );
                if (str !== chunks.join("")) {
			throw "String.split() not working as expected, aborting to avoid text corruption";
		}
		// alert("xEncode: chunks = ['" + chunks.join("', '") + "']");
		for (var i = 0; i < chunks.length; i++) {
			var match = /^([CcGgHhJjSsUuĈĉĜĝĤĥĴĵŜŝŬŭ])([Xx]*)/.exec( chunks[i] );
			if (!match) continue;					// might happen on first chunk
			var prefix = encMap[match[1]] || match[1];		// encode first char
			var middle = match[2].replace( /(X)/ig, '$1$1' );	// double any following Xs
			var suffix = chunks[i].substr( match[0].length );	// leave rest as is
			chunks[i] = prefix + middle + suffix;
		}
		return chunks.join("");
	}

	function xDecode (str) {
		// XXX: use a look-ahead assertion to avoid problems with capturing parens in split() on IE
		var chunks = str.split( /(?=[CcGgHhJjSsUu][Xx])/ );
                if (str !== chunks.join("")) {
			throw "String.split() not working as expected, aborting to avoid text corruption";
		}
		// alert("xDecode: chunks = ['" + chunks.join("', '") + "']");
		for (var i = 0; i < chunks.length; i++) {
			var match = /^([CcGgHhJjSsUu])([Xx]*)/.exec( chunks[i] );
			if (!match) continue;					// might happen on first chunk
			var offset = match[2].length % 2;			// 1 = decode, 0 = just collapse Xs
			var prefix = (offset > 0 ? decMap[match[1]] : match[1]);	// decode first char
			var middle = match[2].substr(offset).replace( /(X)X/ig, '$1' );	// halve any following Xs
			var suffix = chunks[i].substr( match[0].length );	// leave rest as is
			chunks[i] = prefix + middle + suffix;
		}
		return chunks.join("");
	}

	var selfTestA = "XXX: Thiŝ example sux, sŭx, suxx, suxxx, suxxxx!";
	var selfTestB = xEncode(selfTestA);
	var selfTestC = xDecode(selfTestB);
        // alert("Selftest: '" + selfTestA + "' -> '" + selfTestB + "' -> '" + selfTestC + "'");
	if (selfTestA !== selfTestC) {
		throw "EoMagicalConversion self-test failed: '" + selfTestA + "' != '" + selfTestC + "'";
	}

	var $form = $('#editform, #mw-upload-form');
	if ($form.length < 1) return;
	var $boxes = $form.find('input, textarea');
	if ($boxes.length < 1) return;

	// Immediately
	$boxes.each( function () {
		var text = $(this).val();
		$(this).val( xEncode( text ) );
	} );

	// On Submit
	$form.submit( function () {
		// $boxes.off('change');
		$boxes.each( function () {
			var text = $(this).val();
			$(this).val( xDecode( text ) );
		} );
	} );
}

if(mw.config.get('wgAction') === 'edit' || mw.config.get('wgAction') === 'submit' || mw.config.get('wgAction') === 'Upload') {
	jQuery(esperantoHandlers);
}