User:SPage (WMF)/JStransforms.js

From mediawiki.org

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.
( function ( $, mw ) {
	if ( !mw.config.get( 'wgTitle' ).match( /^SPage \(WMF\)\/(JS test|ApiEx utility)$/ ) ) {
		return;
	}
	mw.loader.using( 'mediawiki.Uri', function() {
		var transforms = {
			"make API ex": makeApiEx,
			"linkify": makeLinks
		},
		$cpanel;

		/**
		 * given an apiEx uri struct,
		 * returns a {{TNT|ApiEx}} method invocation
		 * e.g. take https://en.wikipedia.org/w/api.php?action=query&list=geosearch&format=json&gscoord=37.786952%7C-122.399523&gsradius=10000&gslimit=10
		 * and turn it into {{TNT|ApiEx | p1=action=query | p2=list=geosearch ... }}
		 */
		function toApiEx( apiEx ) {
			var res = '{{TNT|ApiEx',
				paramCount = 1; // the first ApiEx query param is p1
			if ( apiEx.lang ) {
				res += '\n| lang=' + apiEx.lang;
			}
			if ( apiEx.site ) {
				res += '\n| site=' + apiEx.site;
			}
			$.each ( apiEx.query, function( key, value ) {
				value = value.replace( /\|/g, '{{!}}')
					.replace( / /g, '%20');
				res += '\n| p' + paramCount + '=' + key + '=' + value;
				paramCount++;
			});
			res += '\n}}';
			return res;
		}

		function makeApiEx ( str ) {
			// TODO: This doesn't work if the input has more than one URL in it.
			var uri = new mw.Uri( str ),
				apiEx = {},
				hostMatch;
			if ( uri.host && ( uri.host != 'en.wikipedia.org') ) {
				hostMatch = uri.host.match( /(.*)\.wikipedia.org/ );
				if ( hostMatch && ( hostMatch[1] != 'en') ) {
					apiEx.lang = hostMatch[1];
				} else {
					apiEx.site = uri.host;
				}
			}
			apiEx.query = uri.query;
			return toApiEx( apiEx );
		}

		/**
		 * Given a URL, possibly turn it into an interwiki [[foo:path]] wiki link.
		 */
		function makeIWLinkFromURL( url ) {
			// https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Uri
			var	uri = new mw.Uri( url ),
				path,
				query,
				fragment,
				interwiki = null,
				isWiki = false;
			// Bail if no host or a complex URL like http://usr:pwd@www.example.com:81/path
			if ( !uri.host || uri.user || uri.password || uri.port ) {
				return url + "(WELL AT LEAST IT WAS PROCESSED)";
			}

			// Prepare the rest of the URL for reassembly
			rest = uri.path.replace( /^\//, '');
			if ( !$.isEmptyObject( uri.query ) ) {
				rest += '?' + uri.getQueryString();
			}
			if ( uri.fragment ) {
				rest += '#' + uri.fragment;
			}

			switch ( uri.host.toLowerCase() ) {
				case 'phabricator.wikimedia.org':
					interwiki = 'phab:';
					break;

				case 'www.mediawiki.org':
				case 'mediawiki.org':
					// Assume this is running on mediwiki.org
					interwiki = '';
					isWiki = true;
					break;
				case 'en.wikipedia.org':
					interwiki = 'w:';
					isWiki = true;
					break;
			}

			if ( interwiki === null ) {
				return url;
			}

			if ( isWiki ) {

				// [[mw:Special:Search?search=findme]] doesn't work
				if ( !$.isEmptyObject( uri.query ) ) {
					return url;
				}
				// http://mediawiki.org/w/COPYING won't work as interwiki.
				if ( !rest.match( /^wiki\// ) ) {
					return url;
				}
				rest = rest.replace( /^wiki\//, '');
				// TODO: title within wiki link should change underscores to spaces. Use mw.Title ?
			}
			// NOT adding a text for the wiki link.
			return '[[' + interwiki + rest + ']]';
		}

		/**
		 * Linkify all the things
		 * "T1234 and https://phabricator.wikimedia.org/maniphest/task/create/?projects=dev.wikimedia.org,documentation and https://www.mediawiki.org/wiki/User:SPage_(WMF)/Sandbox#wiki_links"
		 * "but not aT1234, [[phab:T1234]], https://www.mediawiki.org/wiki/Special:Search?search=lookup"
		 */
		function makeLinks ( str ) {
			var 
				// Detects the URLs to pass to makeIWLinkFromURL().
				// from http://stackoverflow.com/a/8943487/1162195 , but
				// * exclude ftp and file
				// * permit path with parentheses, e.g. User:SPage_(WMF)
				// TODO ignore URL if it has square bracket in front or if it's in an href="".
				urlRegex =/(\b(https?):\/\/[-A-Z0-9+&@#\/%?=~_|()!:,.;]*[-A-Z0-9+&@#\/%=~_|)])/ig,
				// Detects T1234, but not T99, thisT1234, phab:T1234, or .org/T1234
				phabTRE = /(^|[^\/:\w])(T\d{3,7})(\W)/g;

			if ( str === '' ) {
				return;
			}
			return str.replace( urlRegex, makeIWLinkFromURL )
				.replace( phabTRE, '$1[[phab:$2|$2]]$3' );
		}

		function doTransform() {
			var res,
				transform;
			transform = $( 'input[name="workJStransform"]:checked' ).val();
			res = transforms[transform]( $( '#inp' ).val() );
			$cpanel.find( '#result').html( res );			
		}

		// Set up the input area
		$cpanel = $( '<div><textarea id="inp" width="50%"cols="50" placeholder="Enter some text here"></textarea></div>' );
		// Create a radio button for each transform
		$.each( transforms, function( key, value ) {
		    var $element=$('<input type="radio" name="workJStransform" value="' + key + '" id="' + key + '"/><label for="' + key + '">' + key + '</label><br>');
		    $cpanel.append( $element );
		} );
		// Check the first radiobutton
		$cpanel.find( '[name="workJStransform"]:first').prop( 'checked', true );
		// Do the transform whenever any input element changes.
		$cpanel.find( '#inp,input[name="workJStransform"]' ).change( doTransform );
		$cpanel.append( '<pre id="result">' );

		$ ( document ).ready( function() {
		    $( '#workArea' ).html(
		        $cpanel
		    );
		}); 
	} ); 
} )( jQuery, mediaWiki );