Jump to content

User:Guywan/Scripts/BulletSort.js

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Guywan (talk | contribs) at 17:04, 3 December 2019. The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
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.
// [[Category:Wikipedia scripts]]
// <nowiki>
$(function()
{
	if(mw.config.get("wgAction") !== "edit") return;
	
	const debug = false;
	
	if(document.onkeyup !== null)
	{
		var original = document.onkeyup;
		
		document.onkeyup = function(e)
		{
			original();
			
	    	if(e.ctrlKey && e.altKey && e.which == 83)
	    	{
				run();
			}
		};
	}
	else document.onkeyup = run;
	
	function run()
	{
		mw.notify("Sorting...", "info");
		
		// Purely to allow 'Sorting...' to display before we start sorting.
		// That's a 100 miliseconds you'll never get back.
		setTimeout(function()
		{
			try
			{
				api = new mw.Api();
				
				const txtarea = document.getElementById("wpTextbox1");
				const start = txtarea.selectionStart;
				const end = txtarea.selectionEnd;
				
				var lines = txtarea.value.substring(start, end).split("\n");
				
				if(debug) console.log(lines);
				
				var level = "*";
		
				// (1) Create the tree.
				var t = tree(level, lines)[0];
				
				if(debug) console.log(t);
				
				// (2) Sort the tree.
				var parsedLines = parse(txtarea.value.substring(start, end)
					// Remove references before parsing.
					.replace(/<ref.*?>.*?<\/ref>/g, ""))
					// Remove HTML tags and comments, as they will impede sorting.
					.replace(/(<\/?[^>]*>)|(<!--.*?-->)/g, "")
					.split("\n");
				
				if(debug) console.log(parsedLines);
					
				map = {};
				for(var i = 0; i < lines.length; i++)
				{
					map[lines[i]] = parsedLines[i].trim();
				}
				
				sort(t.sort(compare));
				
				// (3) Convert the tree back into a string and reset txtarea.
				txtarea.value = txtarea.value.substring(0, start) + join(t) + txtarea.value.substr(end + 1);
				mw.notify("Done.", "info");
			}
			catch(e)
			{
				console.log(e);
				mw.notify("Failed. See your console for more info.", "info");
			}
			
		}, 100);
	}
	
	function tree(level, list)
	{
		var branch = [];
		for(var i = 0; i < list.length; i++)
		{
			var line = list[i];
			
			const match = line.match(/^\*+/);
			
			if(!match) // No level.
			{
				branch[branch.length - 1].append += line + "\n";
			}
			else if(match[0] == level) // Same level.
			{
				branch.push({"text": line, "append": "", "children": null});
			}
			else if(match[0] == level + "*") // Lower level.
			{
				var result = tree(level + "*", list.slice(i));
				
				branch[branch.length - 1].children = result[0];
				
				i += result[1] - 1;
			}
			else // Upper level.
			{
				return [branch, i];
			}
		}
		
		return [branch, i];
	}
		
	function sort(list)
	{
		for(var i = 0; i < list.length; i++)
		{
			if(list[i].children !== null && list[i].children !== undefined)
			{
				list[i].children.sort(compare);
				
				sort(list[i].children);
			}
		}
	}
		
	function join(list)
	{
		joined = "";
		for(var i = 0; i < list.length; i++)
		{
			joined += list[i].text + "\n" + list[i].append;
			
			if(list[i].children !== null)
			{
				joined += join(list[i].children);
			}
		}
		
		return joined;
	}
	
	function compare(a, b)
	{
		return map[a.text].localeCompare(map[b.text]);
	}
	
	function parse(text)
	{
		// Percent-encode some chars that 'encodeURI()' seems to miss.
		text = text.replace(/&/g, "%26").replace(/#/g, "%23");
		
		var response = $.ajax(
		{
			url : `https://en.wikipedia.org/w/api.php?action=parse&contentmodel=wikitext&format=json&text=${encodeURI(text)}`,
			async : false
		});
		
		if(debug) console.log(response.responseText);
		
		return JSON.parse(response.responseText).parse.text["*"];
	}
});
// </nowiki>