User:Attendant/monobook.js

From Lyriki

Jump to: navigation, search

Note - After saving, you may have to bypass your browser's cache to see the changes. Mozilla / Firefox / Safari: hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Command-R on a Macintosh); Konqueror: click Reload or press F5; Opera: clear the cache in Tools → Preferences; Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5.


// originally based on the work for Extra edit buttons by various contributors:
// http://en.wikipedia.org/wiki/User:MarkS/Extra_edit_buttons
// Modified for use with Lyriki.com

// Set BUTTONS to be a coma separated list of the keys in BUTTONS_MAP
// to define what buttons (and in which order) are shown.
var BUTTONS = null;

var BUTTONS_MAP = {
	"CO" : ["http://www.lyriki.com/images/7/74/Button_comment.png", "Comment", "<!--", "-->", "Comment text"],
	"CA" : ["http://www.lyriki.com/images/1/11/Button_category.png", "Category", "[[Category:", "]]", "Category name"],
	"R"  : ["http://www.lyriki.com/images/c/c8/Button_redirect.png", "Redirect", "#REDIRECT [[", "]]", "Article name"],
	"T"  : ["http://www.lyriki.com/images/0/00/Button_template2.png", "Template", "{{", "}}", "Template name"],
	"SM" : ["http://www.lyriki.com/images/5/58/Button_small.png", "Small", "<small>", "</small>", "Small Text"],
	"BI" : ["http://www.lyriki.com/images/5/56/Button_big.png", "Big text", "<big>", "</big>", "Big text"],
	"LY" : ["http://www.lyriki.com/images/5/5b/Button_lyrics.png", "Lyrics Text", "<lyrics>", "</lyrics>", "Lyrics text"],
	"PR" : ["http://www.lyriki.com/images/3/3c/Button_pre.png", "Pre formatted Text", "<pre>", "</pre>", "Pre formatted text"],
	"SB" : ["http://www.lyriki.com/skins/common/images/button_bold.png", "Bold", "<b>", "</b>", "Bold text"],
	"SI" : ["http://www.lyriki.com/skins/common/images/button_italic.png", "Italic", "<i>", "</i>", "Italic text"],
	"SU" : ["http://www.lyriki.com/images/f/fd/Button_underline.png", "Underline", "<u>", "</u>", "Underline text"],
	"SS" : ["http://www.lyriki.com/images/d/db/Button_strikeout.png", "Strikeout", "<s>", "</s>", "Strike out text"],
	"ST" : ["http://www.lyriki.com/images/8/82/Button_teletype.png", "Teletype text", "<tt>", "</tt>", "Teletype text"],
	"CUS": ["http://www.lyriki.com/images/9/93/Button_cleanupsong.png", "Cleanup Song", "", "", ""],
	"CUA": ["http://www.lyriki.com/images/6/60/Button_cleanupalbum.png", "Cleanup Album", "", "", ""],
};

if ( ! wgIsArticle ) // only if edit
{
	addOnloadHook( initButtons );
	hookEvent( "load", installButtonHandlers );
}

//=======================================================================
// BUTTONS SETUP AND INITIALIZATION FUNCTIONS
//=======================================================================

function initButtons()
{
	// English Wikipedia creates 11 extra buttons which are stored in mwCustomEditButtons rather
	// than mwEditButtons. However, there is no guarantee it will always be 11 so we count them here.
	var enExtraButtons = mwCustomEditButtons.length;

	var buttonsKeys = [];
	if ( typeof BUTTONS != "string" || BUTTONS.toLowerCase() == "all" ) // can be modified
		for ( b in BUTTONS_MAP )
			buttonsKeys.push( b );
	else
		buttonsKeys = BUTTONS.toUpperCase().split( "," );

	// Add the media wiki standard buttons into the available buttons
	for ( b in mwEditButtons )
	{
		// add standard buttons for full XEB order changing
		BUTTONS_MAP[b] = [
			mwEditButtons[b].imageFile,
			mwEditButtons[b].speedTip,
			mwEditButtons[b].tagOpen,
			mwEditButtons[b].tagClose,
			mwEditButtons[b].sampleText
		];
	}

	// Build the new buttons
	for ( idx = 0; idx < buttonsKeys.length; idx++ )
	{
		var button = BUTTONS_MAP[buttonsKeys[idx]];
		if ( typeof button == "object" )
		{
			mwCustomEditButtons.push( {
				"imageFile"	: button[0],
				"speedTip"	: button[1],
				"tagOpen"	: button[2],
				"tagClose"	: button[3],
				"sampleText": button[4]
			} );
		}
	}
}

// Adds extended onclick-function to some buttons
function installButtonHandlers()
{
	if ( ! (allEditButtons = document.getElementById( "toolbar" )) )
		return false;

	if ( typeof editform != "undefined" )
		if ( ! (window.editform = document.forms["editform"]) )
			return false;

	//installButtonHandler( IMG_ROOT + "button_cleanupsong.png", cleanSongPage )
	//installButtonHandler( IMG_ROOT + "button_cleanupalbum.png", cleanAlbumPage )
	installButtonHandler( BUTTONS_MAP["CUS"][0], cleanSongPage )
	installButtonHandler( BUTTONS_MAP["CUA"][0], cleanAlbumPage )


	function installButtonHandler( imageURL, newFunction )
	{
		if ( ! (allEditButtons = document.getElementById( "toolbar" )) )
			return false;

		if ( typeof editform != "undefined" )
			if ( !(window.editform = document.forms["editform"]) )
				return false;

		allEditButtons = allEditButtons.getElementsByTagName( "img" );
		for( i = 0; i < allEditButtons.length; i++ )
		{
			if ( allEditButtons[i].src == imageURL )
				allEditButtons[i].onclick = newFunction;
		}
	}
}


//=======================================================================
// GENERAL FUNCTIONS
//=======================================================================

function debug( msg )
{
	alert( msg );
}

function getArticleTitle()
{
	return new String( wgTitle );
}

function getArticleText()
{
	var textarea;

	if ( document.editform )
		textarea = document.editform.wpTextbox1;
	else
	{
		// some alternate form? take the first one we can find
		var textareas = document.getElementsByTagName( "textarea" );
		textarea = textareas[0];
	}

	if ( typeof textarea != "object" )
		return "";

	if ( is_gecko || is_khtml || is_safari )
		return normalizeEOL( textarea.value.substring( 0, textarea.value.length ) );
	else // is_opera or "is_ie"
	{
		textarea.focus();
		var range = document.selection.createRange();
		return normalizeEOL( range.text );
	}
}

function setArticleText( newText )
{
	var textarea;

	if ( document.editform )
		textarea = document.editform.wpTextbox1;
	else
	{
		// some alternate form? take the first one we can find
		var textareas = document.getElementsByTagName( "textarea" );
		textarea = textareas[0];
	}

	if ( typeof textarea != "object" )
		return;

	if ( is_gecko || is_khtml || is_safari )
	{
		var textScroll = textarea.scrollTop; // save textarea scroll position
		textarea.focus(); // get current selection
		textarea.value = newText;
		textarea.scrollTop = textScroll; // restore textarea scroll position
	}
	else // is_opera or "is_ie"
	{
		// save window scroll position
		if ( document.documentElement && document.documentElement.scrollTop )
			var winScroll = document.documentElement.scrollTop
		else if ( document.body )
			var winScroll = document.body.scrollTop;
		textarea.focus();
		var range = document.selection.createRange();
		range.text = newText;
		//restore window scroll position
		if ( document.documentElement && document.documentElement.scrollTop )
			document.documentElement.scrollTop = winScroll
		else if ( document.body )
			document.body.scrollTop = winScroll;
	}
}

function showEditWarning( header, message )
{
	if ( typeof( message ) == "undefined" )
		message = "";

	header = escapeQuotesHTML( header );
	message = escapeQuotesHTML( message );

	text1 = "<table style='border: 1px solid #aaa; background-color: #f9f9f9; width: 100%; margin: 0 auto 1em auto; padding: .2em;'><tr><td align='left' rowspan='2'><a href='/mediawiki/index.php/Image:Warning_icon.png' class='image' title='Warning'><img alt='Warning' src='/mediawiki/images/a/ab/Warning_icon.png' width='50' height='50' border='0' /></a></td><td align='center' width='100%'><span style='font-size: 100%'><b>" + header + "</b></span></td></tr><tr><td align='center' width='100%'><span style='font-size: 85%'>" + message + "</span></td></tr></table>";
	jsMsg( text1 );
}


//=======================================================================
// STRING FUNCTIONS
//=======================================================================

var CORRECT_CASE = true;
var WORD_SEPARATORS = " \t\n()[],\\.;:-¿?¡!\"/\\";
var LOWER_CASE_WORDS = [
	"the", "a", "an",									// articles
	"and", "but", "or", "nor",							// conjunctions
	"'n'", "'n", "n'",									// and contractions
	"as", "at", "by", "for", "in", "of", "on", "to",	// short prepositions
	//"from", "into", "onto", "with", "over"			// not so short prepositions
	"feat", "vs",										// special words
];

function normalizeEOL( string )
{
	return string.replace( /\r\n/g, "\n" ).replace( /\r/g, "\n" );
}

function ltrim( string )
{
	return string.replace( /^\s+/, "" );
}

function rtrim( string )
{
	return string.replace( /\s+$/, "" );
}

function trim( string )
{
	return rtrim( ltrim( string ) );
}

function removeVocalAccents( string )
{
	string = string.replace( /á|à|ä|â|å|ã/g, "a" );
	string = string.replace( /Á|À|Ä|Â|Å|Ã/g, "A" );
	string = string.replace( /é|è|ë|ê/g, "e" );
	string = string.replace( /É|È|Ë|Ê/g, "E" );
	string = string.replace( /í|ì|ï|î/g, "i" );
	string = string.replace( /Í|Ì|Ï|Î/g, "I" );
	string = string.replace( /ó|ò|ö|ô/g, "o" );
	string = string.replace( /Ó|Ò|Ö|Ô/g, "O" );
	string = string.replace( /ú|ù|ü|û/g, "u" );
	string = string.replace( /Ú|Ù|Ü|Û/g, "U" );
	return string;
}

function capitalize( string, downcase )
{
	if ( typeof( downcase ) == "undefined" )
		downcase = false;

	return string.slice( 0, 1 ).toUpperCase() + string.slice( 1 );
}

function titlecase( string, correctCase, downcase )
{
	if ( typeof( correctCase ) == "undefined" )
		correctCase = true;
	if ( typeof( downcase ) == "undefined" )
		downcase = false;

	string = capitalize( string, downcase );

	var newString = "";
	var wordStart = true;
	for ( var idx = 0; idx < string.length; ++idx )
	{
		var char = string.charAt( idx );
		if ( wordStart )
		{
			if ( WORD_SEPARATORS.indexOf( char ) == -1 )
			{
				wordStart = false;
				newString += char.toUpperCase();
			}
			else
				newString += char;
		}
		else
		{
			newString += char;
 			if ( WORD_SEPARATORS.indexOf( char ) != -1 )
				wordStart = true;
		}
	}

	if ( correctCase )
	{
		for ( var idx = 0; idx < LOWER_CASE_WORDS.length; ++idx )
		{
			lcWord = LOWER_CASE_WORDS[idx];
			newString = newString.replace( new RegExp( " " + lcWord + "([ ,;:\.-?!\"/\\\\\\)])", "gi" ), " " + lcWord + "$1" );
		}
	}

	return newString;
}


//=======================================================================
// LYRIKI SPECIFIC FUNCTIONS
//=======================================================================

function findTemplateParam( paramName, content, allowNestedTemplates )
{
	if ( typeof( allowNestedTemplates ) == "undefined" )
		allowNestedTemplates = false;

	var md;

	if ( allowNestedTemplates )
		md = new RegExp( "\\| *" + paramName + " *= *(.+)[\n\\|\\}]", "m" ).exec( content )
	else
		md = new RegExp( "\\| *" + paramName + " *= *([^\\|\\}]+)[\n\\|\\}]" ).exec( content )

	if ( ! md )
		return false;

	var param = trim( md[1] );
	return param.length > 0 ? param : false;
}

function cleanSongPage()
{
	var articleTitle = getArticleTitle();
	var articleText = getArticleText();

	var md;

	var song = "";
	if ( md = findTemplateParam( "song", articleText ) )
		song = cleanupToken( md, CORRECT_CASE );
	else if ( md = /^([^\n]+)<br *\/?>/m.exec( articleText ) )
		song = cleanupToken( md[1], CORRECT_CASE );
	else if ( md = /^[^:]+:(.+)/.exec( articleTitle ) )
		song = cleanupToken( md[1], CORRECT_CASE );

	var artists = [];
	if ( md = findTemplateParam( "artist", articleText ) )
		artists = [ cleanupToken( md, CORRECT_CASE ) ];
	else if ( md = findTemplateParam( "artists", articleText, true ) )
	{
		var addArtistFunction = function addArtist( ms, m1, o, s ) { artists.push( trim( m1 ) ); };
		md.replace( /\{\{ *[Ss]ong artist *\|([^\|\}]+)/g, addArtistFunction );
		md.replace( /\[\[([^\|\]]+)/g, addArtistFunction );
	}
	else if ( md = /^Artist: \[\[([^\|\]]+)\]\](<br *\/?>|)\n/m.exec( articleText ) )
		artists = [ cleanupToken( md[1], CORRECT_CASE ) ];
	else if ( md = /^([^:]+):/.exec( articleTitle ) )
		artists = [ cleanupToken( md[1], CORRECT_CASE ) ];

	var albums = [];
	if ( md = findTemplateParam( "album", articleText ) )
	{
		albumName = cleanupToken( md, CORRECT_CASE );
		albumYear = "";
		if ( md = findTemplateParam( "year", articleText ) )
			albumYear = cleanupToken( md );
		albums = [ [artists[0], albumName, albumYear] ];
	}
	else if ( md = findTemplateParam( "albums", articleText, true ) )
	{
		function addAlbum( ms, m1, m2, m3, o, s ) {
			albums.push( [
				cleanupToken( m1, CORRECT_CASE ),
				cleanupToken( m2, CORRECT_CASE ),
				cleanupToken( m3, CORRECT_CASE )
			] );
		};
		md.replace( /\{\{ *[Ss]ong album *\|([^\|]+)\|([^\|]+)\|([^\|\}]+)/g, addAlbum );
		md.replace( /\[\[([^:]+):([^\(]+)\((\d{4})\)(\|[^\]]+|)\]\]/g, addAlbum );
	}
	else if ( md = /^Album: *\[\[([^:]+):([^\(]+)\((\d\d\d\d)\)(\|[^\]]+|)\]\](<br *\/?>|)\n/m.exec( articleText ) )
		albums = [ [cleanupToken( md[1], CORRECT_CASE ), cleanupToken( md[2], CORRECT_CASE ), cleanupToken( md[3] )] ];

	var credits = [];
	if ( md = findTemplateParam( "credits", articleText ) )
	{
		credits = md.split( /\s*<br ?\/?>\s*/i );
		if ( credits.length == 1 )
			credits = credits[0].split( /\s*\/\s*/ );
		if ( credits.length == 1 )
			credits = credits[0].split( /\s*;\s*/ );
		if ( credits.length == 1 )
			credits = credits[0].split( /\s*,\s*/ );
		for ( var idx = 0; idx < credits.length; ++idx )
			credits[idx] = cleanupToken( credits[idx], CORRECT_CASE );
	}

	var lyricist = [];
	if ( md = findTemplateParam( "lyricist", articleText ) )
	{
		lyricist = md.split( /\s*<br ?\/?>\s*/i );
		if ( lyricist.length == 1 )
			lyricist = lyricist[0].split( /\s*\/\s*/ );
		if ( lyricist.length == 1 )
			lyricist = lyricist[0].split( /\s*;\s*/ );
		if ( lyricist.length == 1 )
			lyricist = lyricist[0].split( /\s*,\s*/ );
		for ( var idx = 0; idx < lyricist.length; ++idx )
			lyricist[idx] = cleanupToken( lyricist[idx], CORRECT_CASE );
	}

	var lyrics = "";
	if ( md = /<lyrics>(.|\s)*<\/?lyrics>/i.exec( articleText ) )
		lyrics = cleanupLyrics( md[0].replace( /^<lyrics>/i, "" ).replace( /<\/?lyrics>$/i, "" ) );
	else
		lyrics = cleanupLyrics( getArticleText() );


	var sortTitle = getSortName( song );
	var sortLetter = getSortLetter( song );

	articleText =
		"{{Song\n" +
		"| song     = " + song + "\n" +
		buildArtists( artists ) +
		buildAlbums( artists.length > 1, albums ) +
		"| credits  = " + credits.join( "<br />" ) + "\n" +
		"| lyricist = " + lyricist.join( "<br />" ) + "\n" +
		"}}\n" +
		"\n" +
		"<lyrics>" + lyrics + "</lyrics>\n" +
		"\n" +
		"{{C:Song|" + sortLetter + "|" + sortTitle + "}}";

	var oldArticleText = getArticleText();
	if ( oldArticleText != articleText )
	{
		showEditWarning( "Please, make sure the introduced changes haven't messed up with any previously valid content!" );
		setArticleText( articleText );
	}

	function buildArtists( artists )
	{
		if ( artists.length > 1 )
		{
			var ret = "| artists  = ";
			var idx = 0;
			for ( ; idx < artists.length - 1; ++idx )
				ret += "{{song artist|" + artists[idx] + "}}" + (idx < artists.length - 2 ? ", " : " and ");
			return ret + "{{song artist|" + artists[idx] + "}}\n";
		}
		else
			return "| artist   = " + artists[0] + "\n";
	}

	function buildAlbums( multipleArtists, albums )
	{
		if ( albums.length == 0 )
			return multipleArtists ? "| albums   = \n" : "| album    = \n| year     = \n";
		else if ( albums.length == 1 && ! multipleArtists )
			return "| album    = " + albums[0][1] + "\n| year     = " + albums[0][2] + "\n";
		else
		{
			var ret = "| albums   = ";
			var idx = 0;
			for ( ; idx < albums.length - 1; ++idx )
				ret += "{{song album|" + albums[idx][0] + "|" + albums[idx][1] + "|" + albums[idx][2] + "}}<br />";
			return ret + "{{song album|" + albums[idx][0] + "|" + albums[idx][1] + "|" + albums[idx][2] + "}}\n";
		}
	}

// 	function split( value, sepRegExp )
// 	{
// 		if ( typeof( value ) == "string" )
// 			return value.split( sepRegExp );
// 		else
// 		{
// 			var tokens = [];
// 			for ( var idx = 0; idx < value.length; ++idx )
// 				tokens[] = value[idx].split( sepRegExp );
// 			return tokens[];
// 		}
// 	}
}

function cleanAlbumPage()
{
	var articleTitle = getArticleTitle();
	var articleText = getArticleText();

	var md;

	var album = "";
	if ( md = findTemplateParam( "album", articleText ) )
		album = cleanupToken( md, CORRECT_CASE );
	else if ( md = /\[\[Image:([^\|]+)\|thumb\|\d+px\|([^\]]+)\]\]/m.exec( articleText ) )
		album = cleanupToken( md[2], CORRECT_CASE );
	else if ( md = /{{C:Album\|[^\|]+\|([^\}]+)}}/m.exec( articleText ) )
		album = cleanupToken( md[1], CORRECT_CASE );
	else if ( md = /^[^:]+:(.+) \(\d{4}\) *$/.exec( articleTitle ) )
		album = cleanupToken( md[1], CORRECT_CASE );

	var artists = [];
	if ( md = findTemplateParam( "artist", articleText ) )
		artists = [cleanupToken( md, CORRECT_CASE )];
	else if ( md = findTemplateParam( "artists", articleText, true ) )
	{
		function addArtist( ms, m1, o, s ) { artists.push( trim( m1 ) ); };
		md.replace( /\{\{ *[Aa]lbum artist *\|([^\|\}]+)/g, addArtist );
		md.replace( /\[\[([^\|\]]+)/g, addArtist );
	}
	else if ( md = /\|\s*Artist:\s*\[\[([^\]]+)\]\]/mi.exec( articleText ) )
		artists = [cleanupToken( md[1], CORRECT_CASE )];
	else if ( md = /^([^:]+):/.exec( articleTitle ) )
		artists = [ cleanupToken( md[1], CORRECT_CASE ) ];

	var released = "";
	if ( md = findTemplateParam( "released", articleText ) )
		released = cleanupToken( md );
	else if ( md = /\|\s*(Published|Released|Release Date):\s*(.*)$/m.exec( articleText ) )
		released = cleanupToken( md[2] );
	else if ( md = /^[^:]+:.+ \((\d{4})\) *$/.exec( articleTitle ) )
		released = cleanupToken( md[1] );

	var year = ""
	if ( released.length > 0 )
	{
		var releaseDate = parseDate( released );

		if ( releaseDate["day"] > 0 && releaseDate["month"] > 0 && releaseDate["year"] > 0 )
			released = releaseDate["month_long"] + " " + releaseDate["day"] + ", " + releaseDate["year"];
		else if ( releaseDate["month"] > 0 && releaseDate["year"] > 0 )
			released = releaseDate["month_long"] + ", " + releaseDate["year"];
		else if ( releaseDate["year"] > 0 )
			released = releaseDate["year"];

		year = releaseDate["year"].toString();
	}

	var image = "";
	if ( md = findTemplateParam( "image", articleText ) )
		image = cleanupToken( md );
	else if ( md = /\[\[Image:([^\|\]]+)(\|[^\]]+|)\]\]/.exec( articleText ) )
		image = cleanupToken( md[1] );
	if ( new RegExp( "^AlbumArt-" + artists[0] + "-" + album + " \\(" + year + "\\)\\." ).test( image ) )
		image = "";

	var wikipedia = "";
	if ( md = findTemplateParam( "wikipedia", articleText ) )
		wikipedia = cleanupToken( md );
	var allmusicguide = "";
	if ( md = findTemplateParam( "allmusicguide", articleText ) )
		allmusicguide = cleanupToken( md );
	var lastfm = "";
	if ( md = findTemplateParam( "lastfm", articleText ) )
		lastfm = cleanupToken( md );
	var musicbrainz = "";
	if ( md = findTemplateParam( "musicbrainz", articleText ) )
		musicbrainz = cleanupToken( md );

	var sortTitle = getSortName( album );
	var sortLetter = getSortLetter( album );

	var tracks = convertSongLinks( articleText );

	articleText =
		"{{Album\n" +
		"| album    = " + album + "\n" +
		buildArtists( artists ) +
		"| released = " + released + "\n" +
		(image.length > 0 ? "| image    = " + image + "\n" : "") +
		"| tracks   = \n" + tracks + "\n" +
		(wikipedia.length > 0 ? "| wikipedia = " + wikipedia + "\n" : "") +
		(allmusicguide.length > 0 ? "| allmusicguide = " + allmusicguide + "\n" : "") +
		(lastfm.length > 0 ? "| lastfm = " + lastfm + "\n" : "") +
		(musicbrainz.length > 0 ? "| musicbrainz = " + musicbrainz + "\n" : "") +
		"}}\n" +
		"\n" +
		"{{C:Album|" + sortLetter + "|" + sortTitle + "}}";

	var oldArticleText = getArticleText();
	if ( oldArticleText != articleText )
	{
		showEditWarning( "Please, make sure the introduced changes haven't messed up with any previously valid content!" );
		setArticleText( articleText );
	}

	function buildArtists( artists )
	{
		if ( artists.length > 1 )
		{
			var ret = "| artists  = ";
			var idx = 0;
			for ( ; idx < artists.length - 1; ++idx )
				ret += "{{album artist|" + artists[idx] + "}}" + (idx < artists.length - 2 ? ", " : " and ");
			return ret + "{{album artist|" + artists[idx] + "}}\n";
		}
		else
			return "| artist   = " + artists[0] + "\n";
	}
}

function convertSongLinks( content )
{
	if ( typeof( correctCase ) == "undefined" )
		correctCase = true;

	var tracks = "";
	content.replace( /# *\[\[([^:\]]+):([^\|\]]+)\|([^\]]+)\]\] *(<small>\s*\(?)?([0-9]+:[0-9]{2})?(\)?<\/small>)?/g, matcher1 );
	content.replace( /# *\{\{ *[Ss]ong link *\|(.*)\}\}/g, matcher2 );
	return trim( tracks );

	function matcher1( matchedString, artist, song, disp, m4, len, m6, offset, string )
	{
		if ( artist != "Image" )
			buildSongLink( artist, song, len, "", disp );
	}

	function matcher2( matchedString, m1, offset, string )
	{
		var param = 0;
		var tokens = m1.split( "|" );
		for ( var idx = 0; idx < tokens.length; ++idx )
		{
			if ( md = /^ *disp *= *(.*)/.exec( tokens[idx] ) )
			{
				var disp = tokens[idx];
				tokens.splice( idx, 1 );
				tokens.push( disp );
				break;
			}
		}
		buildSongLink( tokens[0], tokens[1], tokens[2], tokens[3], tokens[4] );
	}

	function buildSongLink( artist, song, len, info, disp )
	{
		if ( typeof( len ) != "string" )
			len = "";
		if ( typeof( info ) != "string" )
			info = "";
		if ( typeof( disp ) != "string" )
			disp = "";

		artist = cleanupToken( artist, CORRECT_CASE );
		song = cleanupToken( song, CORRECT_CASE );
		info = cleanupToken( info, CORRECT_CASE );
		disp = cleanupToken( disp, CORRECT_CASE );

		tracks += "\n# {{song link|" + artist + "|" + song;
		if ( len.length > 0 || info.length > 0 )
			tracks += "|" + len;
		if ( info.length > 0 )
			tracks += "|" + info;
		if ( disp.length > 0 && disp != song )
			tracks += "|disp=" + disp;
		tracks += "}}";
	}
}

function cleanupToken( token, correctCase )
{
	if ( typeof( correctCase ) == "undefined" )
		correctCase = false;

	token = trim( token.replace( /_/g, " " ) );
	if ( correctCase )
		token = titlecase( token, true );
	return token;
}

function cleanupTitleToken( token, downcase )
{
	if ( typeof( downcase ) == "undefined" )
		downcase = false;

	token = token.replace( /\[[^\]\[]*\]/g, "" );
	token = token.replace( /[\[|\]].*$/g, "" );
	token = token.replace( /`|´/g, "'" );
	token = token.replace( /''|«|»/g, "\"" );
	token = token.replace( /( ){2,}/g, " " );
	token = token.replace( /\+/g, "and" );
	token = trim( token );
	return titlecase( token, true, downcase );
}

function cleanupLyrics( lyrics )
{
	var prevLine = "";
	var newLines = [];
	var oldLines = lyrics.split( "\n" );

	for ( var idx = 0; idx < oldLines.length; ++idx )
	{
		var line = oldLines[idx];

		// remove unnecesary spaces
		line = line.replace( /(\t| )+/g, " " );
		line = trim( line );

		// remove : at the start
		line = line.replace( /^:/, "" );

		// quotes and double quotes
		line = line.replace( /`|´|‘|’|‘|’/g, "'" );
		line = line.replace( /''|&quot;|“|”|«|»|„|”/g, "\"" );

		// suspensive points
		line = line.replace( /…+/g, "..." );
		line = line.replace( /[,;]?\.{2,}/g, "..." );

		// add space after '?', '!', ',', ';', ':', '.', ')' and ']' if not present
		line = line.replace( /([^\.]?[\?!,;:\.\)\]])([^ "'<])/g, "$1 $2" );

		// remove spaces after '¿', '¡', '(' and ')'
		line = line.replace( /([¿¡\(\[]) /g, "$1" );

		// remove spaces before '?', '!', ',', ';', ':', '.', ')' and ']'
		line = line.replace( / ([\?!,;:\.\)\]])/g, "$1" );

		// remove space after ... at the beginning of sentence
		line = line.replace( /^\.\.\. /g, "..." );

		// remove single points at end of sentence
		line = line.replace( /([^\.])\.$/g, "$1" );

		// remove commas and semicolons at end of sentence
		line = line.replace( /[,;]$/g, "" );

		// fix english I pronoun capitalization
		line = line.replace( /([ "'\(\[])i([\ '",;:\.\?!\]\)]|$)/g, "$1I$2" );

		// remove spaces after " or ' at the begin of sentence of before them when at the end
		line = line.replace( /^(["']) /, "$1" );
		line = line.replace( / (["'])$/, "$1" );

		// capitalize first alfabet character of the line
		line = capitalize( line );

		// no more than one empty line at the time
		if ( line.length > 0 || prevLine.length > 0 )
		{
			newLines.push( line );
			prevLine = line;
		}
	}

	if ( newLines.length > 0 && newLines[newLines.length-1].length == 0 )
		newLines.pop();

	return newLines.join( "\n" );
}


function getSortName( token )
{
	token = token.replace( /\[[^\]\[]*\]/g, "" );

	token = token.toLowerCase();

	token = token.replace( /[·\.,;:"`´¿\?¡!\(\)\[\]\{\}<>#\$\+\*%\^]/g, "" );
	token = token.replace( /[\\\/_-]/g, " " );
	token = token.replace( /( ){2,}/g, " " );
	token = token.replace( /&/g, "and" );
	token = trim( token );

	token = token.replace( /^a /i, "" ); // NOTE: only valid for English
	token = token.replace( /^an /i, "" );
	token = token.replace( /^the /i, "" );
	token = token.replace( /^el /i, "" );
	token = token.replace( /^le /i, "" );
	token = token.replace( /^la /i, "" );
	token = token.replace( /^l'([aeiou])/i, "$1" );
	token = token.replace( /^los /i, "" );
	token = token.replace( /^las /i, "" );
	token = token.replace( /^les /i, "" );
	token = token.replace( /'/g, "" );

	token = removeVocalAccents( token );
	token = titlecase( token, false, false );

	return token;
}

function getSortLetter( token )
{
	token = getSortName( token );
	token = trim( token );
	return /^\d/.test( token ) ? "0-9" : token.charAt( 0 )
}

function parseDate( stringDate )
{
	var monthNames = [
		"january", "february", "march", "april", "may", "june", "july",
		"august", "september", "october", "november", "december",
		"jan", "feb", "mar", "apr", "may", "jun",
		"jul", "aug", "sep", "oct", "nov", "dec"
	]

	var date = { "day" : 0, "month" : 0, "year" : 0 };

	if ( md = new RegExp( "^(" + monthNames.join( "|" ) + ")( \\d\\d?|), (\\d{2}|\\d{4})$", "i" ).exec( stringDate ) )
	{
		date["day"] = md[2].length ? parseInt( trim( md[2] ), 10 ) : 0;
		date["month"] = monthNames.indexOf( md[1].toLowerCase() ) + 1;
		date["year"] = parseInt( md[3], 10 ) + (md[3].length == 2 ? 2000 : 0);
	}
	else if ( md = new RegExp( "^(\\d\\d? |)(" + monthNames.join( "|" ) + ") (\\d{2}|\\d{4})$", "i" ).exec( stringDate ) )
	{
		date["day"] = md[1].length ? parseInt( trim( md[1] ), 10 ) : 0;
		date["month"] = monthNames.indexOf( md[2].toLowerCase() ) + 1;
		date["year"] = parseInt( md[3], 10 ) + (md[3].length == 2 ? 2000 : 0);
	}
	else if ( /^(\d{2}|\d{4})-(\d\d?)-(\d\d?)$/.exec( stringDate ) )
	{
		date["day"] = parseInt( md[3], 10 );
		date["month"] = parseInt( md[2], 10 );
		date["year"] = parseInt( md[1], 10 ) + (md[1].length == 2 ? 2000 : 0);
	}
	else if ( md = /^(\d{2}|\d{4})$/.exec( stringDate ) )
	{
		date["year"] = parseInt( md[1], 10 );
		if ( md[1].length == 2 )
			date["year"] = date["year"] + 2000;
	}

	if ( date["month"] > 0 )
	{
		if ( date["month"] > 12 )
			date["month"] = date["month"] - 12;
		monthName = capitalize( monthNames[date["month"] - 1] );
		date["month_long"] = monthName;
		date["month_short"] = monthName.substring( 0, 3 );
	}
	else
	{
		date["month_long"] = "";
		date["month_short"] = "";
	}

	//debug( date["year"] + "-" + date["month"] + "-" + date["month_long"] + "-" + date["month_short"] + "-" + date["day"] );

	return date;
}
Personal tools