User:Naypta/ScriptInstaller.js

Today, we want to talk about User:Naypta/ScriptInstaller.js. This is a topic that has gained great relevance in recent times, and it is important to study it in depth to understand its impact on our society. Throughout this article, we will explore different aspects of User:Naypta/ScriptInstaller.js, from its origin and evolution to its influence in various areas. In addition, we will analyze the different perspectives that exist on User:Naypta/ScriptInstaller.js, in order to offer a comprehensive and objective vision. Without a doubt, User:Naypta/ScriptInstaller.js is a topic that invites us to reflect and debate, and we are sure that this article will be enriching for our readers.
//
// ScriptInstaller
// Forked from User:Equazcion/ScriptInstaller.js
// Updated to work for the new APIs by Naypta
//
(function($, mw){
	'use strict';

	var wgPageName = mw.config.get('wgPageName');
	var wgUserName = mw.config.get('wgUserName');
	var wgNamespaceNumber = mw.config.get('wgNamespaceNumber');
	var jsPage = false;
	
	// Never do anything in article space
	if (wgNamespaceNumber === 0){
		return;
	}

	// Handle .js pages
	if ((wgPageName.lastIndexOf('.js') == wgPageName.length - 3) && (mw.config.get('wgAction') == 'view') && (wgNamespaceNumber > -1)) {
		
		// Exclude users' own common.js and skin.js pages
		var fixedUn = wgUserName.replace(/ /g,'_');
		if ((wgPageName != 'User:' + fixedUn + '/common.js') && 
			(wgPageName != 'User:' + fixedUn + '/monobook.js') &&
			(wgPageName != 'User:' + fixedUn + '/minerva.js') &&
			(wgPageName != 'User:' + fixedUn + '/vector.js') &&
			(wgPageName != 'User:' + fixedUn + '/modern.js') &&
			(wgPageName != 'User:' + fixedUn + '/cologneblue.js') &&
			(wgPageName != 'User:' + fixedUn + '/timeless.js') &&
			(wgPageName != 'User:Equazcion/ScriptInstaller.js') &&
			(wgPageName != 'User:Naypta/ScriptInstaller.js')){
				importStylesheet('User:Equazcion/ScriptInstaller.css');
				
				// Set a flag so the rest of the script knows we're on a .js page
				jsPage = true;
				
				// Append the install link to the header, along with a "scriptInstallerLink" class for use by the rest of the script
				$('h1#firstHeading').append('<span style="font-size:0.8em;font-weight:bold;" id="' + wgPageName + '" class="scriptInstallerLink jsPage"></span>');
		}
	}
	
	// If script links are found on the page, start the music. Detection is based on span tags with "scriptInstallerLink" class, which are added by {{userscript}}.
	// Also run if we're on User:Equazcion/scriptInstaller, where we'll simply provide access to the installed script list and uninstall links
	if ((($('span.scriptInstallerLink').length > 0) && (mw.config.get('wgAction') != 'submit') && (mw.config.get('wgAction') != 'edit')) || (wgPageName == 'User:Equazcion/ScriptInstaller' || wgPageName == 'User:Naypta/ScriptInstaller')){
		
		if (jsPage !== true) {
			importStylesheet('User:Equazcion/ScriptInstaller.css'); // Stylesheet already fetched above on .js pages
		}
		if (wgPageName == 'User:Equazcion/ScriptInstaller' || wgPageName == 'User:Naypta/ScriptInstaller') {
			var homePage = true; // Set a flag if we're running the limited User:Equazcion/ScriptInstaller functions
		}
		
		// Set URL prefix
		var pre = location.protocol + '//' + mw.config.get('wgPageContentLanguage') + '.' + mw.config.get('wgNoticeProject') + '.org' + '/w/index.php?title=';
		
		// Set interface text
		var installerTitle = 'You currently have the following scripts installed <div class="titleBadge"><a href="' + pre + 'User:Naypta/ScriptInstaller' + '">Script Installer</a></div>';
		var installerMessage = 'Only scripts installed using <span style="font-weight:bold">Script Installer</span> are shown here. To uninstall a script, click "Uninstall".'; 
		var pipe = '<span style="font-size:1.1em;"> | </span>';
		var installerLink = 'Install';
		var installed = 'Installed';
		var unInstallerLink = 'Uninstall';
		var noauto = 'Must be installed manually';
	
		// Set up the regex pattern for later
		var regexObject = new RegExp( 'importScript\\(\'(.*)\'\\); \\/\\/Linkback: \\\\] Added by Script installer' , );
		
		// Create array for installed script paths
		var installedScripts = ;
		
		// Append the box of installed scripts. Hide unless we're on a designated installation page
		$('div#contentSub').after('<div hidden="hidden" class="scriptInstaller"></div>');
		
		// Set parameters for common.js ajax request	
		var request4 = {
			action:"query", 
			titles: "User:" + mw.config.get("wgUserName") + "/common.js", 
			prop: "revisions|info", 
			intoken: "edit", 
			rvprop: "content",
			indexpageids: 1,
			format: "xml"
		};
		
		// Do common.js ajax request
		$.get(mw.config.get("wgScriptPath")+"/api.php", request4, function(response4){
			
			// Grab common.js content and split by lines 
			var lines = $(response4).find('rev').text().split('\n');
			
			// Use the regex to iterate through the lines, looking for the ones that ScriptInstaller added
			$.each(lines, function(index, value){
				var match = regexObject.exec(value);
				
				// Put the paths of the matches into the array of installed scripts
				if (match !== null){
					installedScripts.push(match);
				}
			});
			
			// If none were found, remove the installed script list box. Otherwise fade-in the box and set up the toggle link
			if (installedScripts.length < 1){
				$('div.scriptInstaller').remove();
			} else if ((wgPageName == 'Wikipedia:WikiProject_User_scripts/Scripts') || (wgPageName == 'Wikipedia:WikiProject_User_scripts') || 
				(wgPageName == 'Wikipedia:User_scripts') || (jsPage === true) || (homePage === true)){
				
				// Insert script list toggle link
				var toggleMessage = ((jsPage === true) || (homePage === true)) ? 'Show installed script list' : 'Hide installed script list';
				$('.firstHeading').append(' <a style="font-weight:bold;font-size:10px" class="scriptinstallerTog" href="#bbx">' + toggleMessage + '</a>');
				
				// The function to set the toggle link to
				function setScriptInstallerToggle(){
					$('.scriptinstallerTog').click(function(){
						if ($('.scriptinstallerTog').html() == "Show installed script list"){
							$('.scriptInstaller').fadeIn(500);
							$('.scriptinstallerTog').html('Hide installed script list');
						} else {
							$('.scriptInstaller').fadeOut(200);
							$('.scriptinstallerTog').html('Show installed script list');
						}
					});
				}
				
				// Set the toggle link function. Also fade the box in initially, if we're at the script listing page.
				if ((jsPage !== true) && (homePage !== true)){ 
					setTimeout(function(){
						$('.scriptInstaller').fadeIn(800, function(){ setScriptInstallerToggle(); });
					}, 500);
				} else {
					setScriptInstallerToggle();
				}					
			}
			
			// Start building the code for display of the installed list. Iterate through each installed script in the array
			var installedList = '<ul style="list-style-type:none;">';
			$.each(installedScripts, function(index, value){
				
				// For each script already installed, change the install links (into "installed" messages) that are on the current page (if any)
				$('span.scriptInstallerLink')
					.attr('id','installed' + index)
					.addClass('installed')
					.html(installed)
					.css('font-weight','bold');
				if (jsPage === true)
					$('span.scriptInstallerLink')
						.attr('id','installed' + index)
						.addClass('installed')
						.html(installed)
						.css('font-weight','bold');
				
				// Add an HTML list element for each installed script, containing .js and uninstall links
				installedList = installedList + '<li>' + 
					'<a href="#installerLink" class="unInstallerLink">' + unInstallerLink + '</a>: ' +
					'<a href="' + pre + value + '">' + decodeURIComponent(value) + '</a>' + 
				'</li>'; 
			});
			
			// Cap off the list of installed scripts
			installedList = installedList + '</ul>';
			
			// Build and append the rest if the list box code, and insert our constructed list of installed scripts
			$('.scriptInstaller').html('<div class="installerTitle">' + installerTitle + '</div>' +	
			'<div class="container1">' + 
					'<div class="installerMessage">' + installerMessage + '</div>' + 
					'<div class="uninstallList">' + installedList + '</div>' + 
			'</div>');
			
			// Iterate through each line in the installed list and set the click function for their uninstall links
			$('.scriptInstaller li').each(function(){
				var path = $(this).find('a:last').html();
				$(this).find('a:first').click(function(){
					
					$('body').append('<div class="overlay" style="background-color:#000;opacity:.4;position:fixed;' + 
						'top:0;left:0;width:100%;height:100%;z-index:500;"></div>');					
						
					$('body').prepend('<div class="arcProg" style="font-weight:bold;box-shadow: 7px 7px 5px #000;font-size:0.9em;line-height:1.5em;' + 
						'z-index:501;opacity:1;position:fixed;width:50%;left:25%;top:30%;background:#F7F7F7;border:#222 ridge 1px;padding:20px;"></div>');
						
					$('.arcProg').append('<div>Uninstalling <span style="font-weight:normal;color:#003366;">' + path + '</span>...</div>');
					
					// Set parameters for the first uninstall ajax request that occurs when the uninstall link is clicked
					var request5 = {
						action:"query", 
						titles: "User:" + mw.config.get("wgUserName") + "/common.js", 
						prop: "revisions|info", 
						intoken: "edit", 
						rvprop: "content",
						indexpageids: 1,
						dataType: "xml",
						format: "xml"
					};
					
					// Send the request
					$.get(mw.config.get("wgScriptPath")+"/api.php", request5, function(response5){
						
						//Grab common.js content and find/replace our line with nothing, thereby removing the script
						var content = $(response5).find('rev').text();
						var newText = content.replace("\n" + "importScript('" + path + "'); //Linkback: ] Added by Script installer", "");
						
						// Set paraemeters for the ajax post that replaces common.js with our edited version
						var request6 = {
							action : "edit",
							title : "User:" + mw.config.get("wgUserName") + "/common.js", 
							text : newText,
							summary : "]: Removed ]",
							token: mw.user.tokens.get("csrfToken")
						};
						
						// Send the ajax post to save the new common.js, then reload the current page
						$.post(mw.config.get("wgScriptPath")+"/api.php", request6, function(response6){
							$('.arcProg').append('<div><span style="color:#00008C">Done!</span> Reloading...</div>');
							location.reload();
						});
					});
				});
			});
		});
		
		// Iterate through each templated (via {{userscript}}) script on the page
		$('span.scriptInstallerLink').each(function(){
			
			// Get the script path, which the template places in the span's ID
			var path = $(this).attr('id');
			path = path.replace(/.2F/g,'/').replace(/\_/g,' ');
			
			// If there's more than one dot left in the path, assume percent encoding was converted to dots. Leave the last dot for ".js"
			if ((path.split(".").length - 1) > 1){
				var parts = path.split('.');
	    		path = parts.slice(0,-1).join('%') + '.' + parts.slice(-1);
			}
			
			// If this path leads to a valid en-wiki .js script in userspace or wikipedia space, add an install link
			if (((path.toLowerCase().substring(0, 5) == "user:") || (path.toLowerCase().substring(0,10) == 'wikipedia:')) && (path.lastIndexOf('.js') == path.length - 3)){
				//var pipe = (jsPage == true) ? '' : ' | ';
				$(this).html('<a href="#installerLink" class="installerLink">' + installerLink + '</a>')
					.before(pipe);
				
				// Set the click function for the install link
				$(this).find('a.installerLink').click(function(){
					
					$('body').append('<div class="overlay" style="background-color:#000;opacity:.4;position:fixed;' + 
						'top:0;left:0;width:100%;height:100%;z-index:500;"></div>');					
						
					$('body').prepend('<div class="arcProg" style="font-weight:bold;box-shadow: 7px 7px 5px #000;font-size:0.9em;line-height:1.5em;' + 
						'z-index:501;opacity:1;position:fixed;width:50%;left:25%;top:30%;background:#F7F7F7;border:#222 ridge 1px;padding:20px;"></div>');
						
					$('.arcProg').append('<div>Installing <span style="font-weight:normal;color:#003366;">' + path + '</span>...</div>');
					
					// Set ajax parameters for the ajax post that occurs when the install link is clicked 
					var request1 = {
						action:"edit", 
						title: "User:" + mw.config.get("wgUserName") + "/common.js", 
						appendtext: "\nimportScript('" + decodeURIComponent(path) + "'); //Linkback: ] Added by Script installer", 
						summary: "]: Added ]", 
						token: mw.user.tokens.get("csrfToken")
					};
					
					// Send the ajax post, which appends our new importScript line to common.js, then reload the current page
					$.post(mw.config.get("wgScriptPath")+"/api.php", request1, function(response1){
						$('.arcProg').append('<div><span style="color:#00008C">Done!</span> Reloading...</div>');
					    location.reload();
					});
				});	
			} else {
				// If this is not a valid path to an en-wiki .js script in user or wikipedia space, add a "must install manually" message
				$(this).html(' | <span class="noauto">' + noauto + '</span>');
			}
		});
	}
})(jQuery, mediaWiki);