MediaWiki:Gadget-ErroriOrtografici.js

Nota: dopo aver pubblicato, potrebbe essere necessario pulire la cache del proprio browser per vedere i cambiamenti.

  • Firefox / Safari: tieni premuto il tasto delle maiuscole Shift e fai clic su Ricarica, oppure premi Ctrl-F5 o Ctrl-R (⌘-R su Mac)
  • Google Chrome: premi Ctrl-Shift-R (⌘-Shift-R su un Mac)
  • Internet Explorer / Edge: tieni premuto il tasto Ctrl e fai clic su Aggiorna, oppure premi Ctrl-F5
  • Opera: premi Ctrl-F5.
/** Vedi la guida alla pagina Aiuto:Gadget ErroriOrtografici
 * Di seguito sono elencate le regole per individuare gli errori ortografici.
 * Si possono suggerire nuove regole o proporre modifiche nella pagina di discussione.
 * È possibile aggiungere le proprie regex personali creando una pagina Utente:nome_utente/customRegex.js
 * Per provare le regex: https://regex101.com
 * Formato: [ /regex/, "descrizione", [ "eccezione1", "eccezione2"] ]	(le eccezioni non sono obbligatorie)
 */
var regex = [
[ /cb[eièì'’]/g,																"OCR: cbe, cbi, cb' per che, chi, ch'", [ "Macbeth"] ],
[ /[a-zA-ZàèìòùÀÈÌÒÙ]{2,}[\.:;,^!\?][abcdefghijklnopqrstuvwxyzA-ZàèìòùÀÈÌÒÙ]/g,	"punteggiatura non seguita da spazio (tranne dev.mo e simili)", [ "www", "align:"] ],
[ /[a-zàèìòùáéíóú]([abdefghjklmnopqrstuvwyz])\1{2,}/g,							"stessa lettera ripetuta 3 volte (tranne numeri romani)" ],
[ /[a-zàèìòùáéíóúA-ZÀÈÌÒÙÁÉÍÓÚ]+[0-9]+[a-zàèìòùáéíóúA-ZÀÈÌÒÙÁÉÍÓÚ]+/g,			"numeri in mezzo alle parole" ],
[ /\s([abdefghjklmnopqrstuvwyzàèìòù])\1{1,}[a-zàèìòùáéíóúA-ZÀÈÌÒÙÁÉÍÓÚ]+/gi,	"stessa lettera ripetuta a inizio parola, tranne numeri romani i, x, c", [ "lloyd", "mms.", "www"] ],
[ /\s([abdefghjklmnopqrstuvwyzàèìòù])\1{1,}\s/g,								"parola costituita interamente dalla stessa lettera ripetuta 2 o più volte tranne numeri romani i, x, c" ],
[ /(?<![?!])(?![?!])(?!\.{1,})([.:;,!\?]){2,}/g,								"più segni di punteggiatura consecutivi (tranne i puntini)" ],
[ /(?<!\.|!|\?)\.{2}(?!\.)/g,													"2 punti fermi consecutivi (ma non 3), tranne dopo ! e ?" ],
[ /[DdFfNnSsUu][EeAa]['’][abcdefghijklmnopqrtuvwxyzàèìòùáéíóúA-ZÀÈÌÒÙÁÉÍÓÚ]/g,	"de’, fe’, ne’, que’ non seguiti da spazio (tranne ’s)"],
[ /([hljmnqrswz])\1[bcdfghklmnpqrstvwxz]/g,										"Doppia H, L, J, M, N, Q, R, S, W, Z seguita da consonante", [ "grizzly", "tyrrhen" ] ],
[ /([bdfkptv])\1[bcdfghkmnpqstvwxz]/g,											"Doppia B, D, F, K, P, T, V seguita da consonante (tranne L o R", [ "Buddha", "http", "www" ] ],
[ /([cg])\1[bcdfgkmnpqstvwxz]/g,												"Doppia C o G seguita da consonante (tranne H, L o R", [ "mdccx"] ],
[ /[a-zàèìòùáéíóú][A-ZÀÈÌÒÙÁÉÍÓÚ]/g,		"minuscola seguita da maiuscola" ],
[ /[àìòùáíóú][a-z]*[àìòùáíóú]/g,			"due accenti nella stessa parola (tranne è é, presenti in parole francesi)" ],
[ /\s[a-zàèìòùáéíóú]*gh[aou]/g,				"gha, gho, ghu", [ "brougham", "afghan"] ],
[ /\s([aeouàèìòù])\1{1,}\s/g,				"parola costituita interamente dalla stessa vocale ripetuta 2 o più volte" ],
[ /\s[bcdfghjklmnpqrstvwz]{2,}[\s:;,!\?]/g,	"parola costituita interamente da 2 o più consonanti", [ "km", "cm", "http" ] ],
[ /po['’][a-zA-ZàèìòùÀÈÌÒÙ]+/g,				"po' senza spazio dopo" ],
[ /l['’][bcdfgklmnpqrstvwxz]/g,				"l' seguito da consonante" ],
[ /([bcdfgjklmnpqrstvwxz]){5,}/g,			"5 o più consonanti consecutive", [ "mdc", "mcmx", "xxx", "clxx", "mccx", "postscriptum", "Innsbruck", "Innspruck", "Armstrong" ] ],
[ /[a-zA-ZàèìòùÀÈÌÒÙ]\s[\.:;,!\?]/g,		"punteggiatura preceduta da spazio", [ ". . ."] ],
[ /\sdell[oaei][\.:;,!\?]/g,				"dello, della e simili seguite da punteggiatura"],
[ /([aeiouàèìòù]){5,}/g,					"5 o più vocali consecutive", [ "cuoiaio", "merciaiuol", "acquaiuol" ] ],
[ /\bim[oa]?[\s\.:;,!\?]\b/g,				"OCR: im, imo, ima per un, uno, una" ],
[ /\s[aeiouàèìòù]{2,}[\s:;,!\?]/g,			"parola costituita interamente da 2 o più vocali", [ "ii", "iii", "io","ai","ei","ài", "aia", "aie", "au", "ou", "où", "eau", "ea", "eo", "eu" ] ],
[ /(\.\s+|\s[a-zàèìòù]+\s+)II [a-zàèìòù]/g,	"II per Il", [ "l II" ] ],
[ /[a-zàèìòùáéíóú]{4,}\. [a-zàèìòùáéíóú]/g,	"Punto fermo seguito da minuscola (tranne abbreviazioni brevi)", [ "ecc."] ],
[ /[a-zàèìòùáéíóúA-ZÀÈÌÒÙ]\*[\s'’]/g,		"Asterischi attaccati al testo"],
[ /\b[Pp]erche\b/g,					"perchè senza accento" ],
[ /\b[Pp]oiche\b/g,					"poichè senza accento" ],
[ /[Pp]iu\b/g,						"più senza accento" ],
[ /\s[Cc]osi\b/g,					"così senza accento" ],
[ /\s[SsLl]i[\.!\?;,:]/g,			"sì, lì senza accento" ],
[ /[Qq]uesl/g,						"OCR: queslo, quesla per questo, questa" ],
[ /(ì|\D1)['’]/g,					"OCR per l'" ],
[ /\s[Dd]eli[oa]\s/g,				"OCR: delia, delio per della, dello" ],
[ /\s[Dd]eir\b/g,					"OCR: deir per dell'" ],
[ /\s[Dd]ell\s/g,					"OCR: dell senza apostrofo" ],
[ /\s[Aa]ir\b/g,					"OCR: air per all'" ],
[ /\s[Nn]eir\b/g,					"OCR: neir per nell'" ],
[ /\s[Cc]oir\b/g,					"OCR: coir per coll'" ],
[ /\s[Pp]iti\b/g,					"OCR: piti per più", [ "pitié" ] ],
[ /\s[iu]h\s/g,						"OCR: ih, uh per in, un" ],
[ /eh['’]/g,						"OCR: eh' per ch'" ],
[ /ch[cn]/g,						"OCR: chc, chn per che" ],
[ /\sohe[\s\.:;,!\?]/g,				"OCR: ohe per che" ],
[ /\bV?ili\b/g,						"OCR: Vili per VIII, ili per III", [ "Vili!"] ],
[ /\sgii\s/g,						"OCR: gii per gli" ],
[ /\sglì?\s/g,						"glì, gl per gli" ],
[ /\s[Ee] stat[oa]\b/g,				"è stato senza accento" ],
[ /\s[Cc]h?['’]e[\s\.:;,!\?]/g,		"c'è, ch'è senza accento" ],
[ /\s[VvNnSs]['’]e[\s\.:;,!\?]/g,	"v'è, s'è, n'è senza accento" ],
[ /\s[Dd]?[Oo]v['’]e[\s\.:;,!\?]/g,	"dov'è senza accento" ],
[ /\s[Cc]o[ms]['’]e[\s\.:;,!\?]/g,	"com'è, cos'è senza accento" ],
[ /\s[Qq]ual[\s'’]e[\s\.:;,!\?]/g,	"qual è, qual'è senza accento" ],
[ /\s[Tt]al\se[\s\.:;,!\?]/g, 		"tal è senza accento" ],
[ /\s[Nn]on\se[\s\.:;,!\?]/g, 		"non è senza accento" ],
[ /\s[Éé][\s\.:;,!\?]/g,			"è (voce verbale) con accento acuto" ],
[ /[ai]l del[\s\.:;,!\?]/g,			"OCR: al del, il del invece di: al ciel, il ciel" ],
[ /o del[\.:;,!\?]/g,				"OCR: o del invece di: o ciel" ],
[ /[Ii'’]ntomo/g,					"OCR: intomo per intorno", [ "sintomo"] ],
[ /[gq]uau/g,						"Quaudo per quando e simili" ],
[ /[•¬flfi]/g,						"Simboli insoliti" ],
[ /\{\{|\}\}|\[\[|\]\]/g,			"Parentesi quadre o grafe di Mediawiki non chiuse bene"],
[ /\S-\s/g,							"Trattini di sillabazione seguiti da spazio" ],
[ /\s—[A-ZÀÈÌÒÙ]/g,					"Trattino di discorso diretto non seguito da spazio"],
[ /[—-]{2,}/g,						"Due o più trattini attaccati"],
[ /I['’][aeiouàèìòù]/g,				"I’ per l’"],
];
customRegex = [];
operaExceptions = [];
var regexList = regex.concat(customRegex);

var pagesToLoad = 50;
var maxIndexPages = 20;
var singlePageText, singleIndexWithoutNs;

$(function() {
	var api = new mw.Api();
	
	// highlight mispelled word on the page
	if (mw.config.get('wgCanonicalNamespace') == 'Page') {
		params = new URLSearchParams(window.location.search);
		var word = params.get('highlight-word');
		if (word) {
			if (mw.config.get('wgAction') == 'view') {
				var regEx = new RegExp("(" + word.replaceAll(".", "\\.") + ")(?!([^<]+)?>)", "g");
				$('#mw-content-text').html($('#mw-content-text').html().replaceAll(regEx, '<span class="highlight-word">' + word + '</span>'));
				$('#ca-edit a').attr('href', $('#ca-edit a').attr('href') + "&highlight-word=" + word);
			} else {
				$('#wpSummary').val("Gadget [[Aiuto:Gadget ErroriOrtografici|ErroriOrtografici]]");
			}
		}
	}

	if (mw.config.get('wgAction') != 'view')
		return;

	openBox = function() {
		$('#mw-content-text').prepend('<div class="box errori-ortografici-box">' +
			'<div class="box-title">Cerca errori ortografici</a>' +
			'<span class="icon-close"></span></div>' +
			'<div class="box-main errori-ortografici-box-main"></div></div>');
		$('.errori-ortografici-box-main').html('<a id="errori-ortografici-help" href="/wiki/Aiuto:Gadget_ErroriOrtografici" class="blue btn" target="_new" title="Consulta la pagina di aiuto su questo strumento (si apre in una nuova scheda)">Guida</a>' +
			'<span id="loading-errori-ortografici">Caricamento in corso...</span><ol id="errori-ortografici-list"></ol>');
		$('.errori-ortografici-box').draggable({
		    create: function( event, ui ) {
		        $(this).css({
		            right: "auto",
		            top: $(this).position().top,
		            left: $(this).position().left
		        });
		    }
		});
		$('.errori-ortografici-box').draggable('option', 'cancel', '.errori-ortografici-box-main');
		$('.errori-ortografici-box .icon-close').click(function() {
			$('.errori-ortografici-box').remove();
		});
	};

	getPureText = function(m, indexPage) {
		puretext = '';
		mode = m;
		singlePage = (indexPage === undefined);
		if (singlePage)
			indexPage = mw.config.get('wgPageName');
		
		$.ajax({
			url: "/w/index.php?&title=" + indexPage.replaceAll("&", "%26").replaceAll("?", "%3F")
		}).done(function(indexResponse) {
			var firstPageHref = $('.prp-index-pagelist-page:not(.quality0):first', indexResponse).attr('href');
			if (firstPageHref == null) {
				console.log("Errore nel caricamento del pagelist per " + indexWithoutNs + " pages " + fromPageNum + "-" + toPageNum);
				return;
			}
			var firstPage = firstPageHref.replace('/wiki/', '').replace('/w/index.php?title=', '').replace('&action=edit&redlink=1', '');
			var lastPage = $('.prp-index-pagelist-page:not(.quality0):last', indexResponse).attr('href').replace('/wiki/', '').replace('/w/index.php?title=', '').replace('&action=edit&redlink=1', '');
			var firstPageNum = parseInt(firstPage.substring(firstPage.lastIndexOf('/') + 1));
			lastPageNum = parseInt(lastPage.substring(lastPage.lastIndexOf('/') + 1));
			indexWithoutNs = indexPage.substring(indexPage.indexOf(':') + 1);
			fromPageNum = firstPageNum;
	
			var q0 = [];
			$('.prp-index-pagelist .quality0', indexResponse).each(function() {
				var thisPage = $(this).attr('href').replace('/wiki/', '').replace('/w/index.php?title=', '').replace('&action=edit&redlink=1', '');
				var thisPageNum = thisPage.substring(thisPage.lastIndexOf('/') + 1);
				q0.push(thisPageNum);
			});
			q0List = q0.join(',');
			
			startTime = Date.now();
			parsePages(lastPageNum, fromPageNum, mode, indexWithoutNs, q0List, puretext, startTime, singlePage);
		});
	};
	
	isException = function(thisRegex, word) {
		var exceptions = operaExceptions;
		if (thisRegex.length > 2)
			exceptions = exceptions.concat(thisRegex[2]);
		for (var i = 0; i < exceptions.length; i++) {
			var ex = exceptions[i].toLowerCase();
			var w = word.toLowerCase();
			if (ex.indexOf(w) > -1 || w.indexOf(ex) > -1) {
				return true;
			}
		}
		return false;
	};
	
	checkForErrors = function(text, thisRegex, indexWithoutNs, isSingleRegex) {
		text = text.replace(/\r?\n/g, ' ');
		var re = thisRegex[0];
		var comment = thisRegex[1];
		var result;
		
		var resultsCount = (text.match(re) || []).length;
		//console.log("Found " + resultsCount + " results for " + re);
		if (isSingleRegex) {
			if (resultsCount == 0) {
				$('#searchRegexResults').html('Nessun risultato trovato.');
			} else if (resultsCount > 1000) {
				$('#searchRegexResults').html('Trovati ' + resultsCount + ' risultati, si suggerisce di cercare un testo più specifico.');
				console.log("Too many results: " + resultsCount);
				return;
			} else {
				$('#searchRegexResults').html('Trovati ' + resultsCount + ' risultati:');
			}
		}
		
		while ((result = re.exec(text)) !== null) {
		    var start = result.index;
		    var end = start + result['0'].length;
		    var wordStart = text.lastIndexOf(' ', start);
		    var wordEnd = text.indexOf(' ', end);
		    var piece = text.substring(start, end);
		    var pieceBefore = text.substring(wordStart, start);
		    var pieceAfter = text.substring(end, wordEnd);
		    var word = pieceBefore + piece + pieceAfter;

			//console.log("piece: " + piece + "_");
			//console.log("word: " + word + "_");

		    if (isException(thisRegex, piece.trim()) || isException(thisRegex, word.trim())) {
		    	continue;
		    }
		    
		    var previousWordStart = text.lastIndexOf(' ', wordStart - 1);
		    var nextWordEnd = text.indexOf(' ', wordEnd + 1);
		    var wordBefore = text.substring(previousWordStart, wordStart);
		    var wordAfter = text.substring(wordEnd, nextWordEnd);
		    
		    var pagenumMatches = text.substring(0, start).match(/\[p\.\s(\d+)\]/g);
		    if (pagenumMatches != null) {
				var pagenum = pagenumMatches[pagenumMatches.length - 1].replace(/\[p\.\s(\d+)\]/, '$1');
				var pageLink = '<a href="/wiki/Page:' + indexWithoutNs.replaceAll("&", "%26").replaceAll("?", "%3F") + '/' + pagenum + '?highlight-word=' + word.trim() + '" target="_new">' 
					+ (singlePage ? 'pag. ' + pagenum : indexWithoutNs + '/' + pagenum) + '</a>';
			    
			    if ($('#errori-ortografici-list li').length < 1000) {
				    $('#errori-ortografici-list').append('<li title="' + comment + 
				    	'" data-indice="' + indexWithoutNs + '" data-pagenum="' + pagenum + '">' + 
				    	pageLink + ': ' + wordBefore + pieceBefore + '<b>' + piece + '</b>' + pieceAfter + wordAfter + '</li>');
				    
				    $("#errori-ortografici-list li").sort(function(a, b) {
					    return ($(b).data('indice')) != ($(a).data('indice')) ?
					        ($(b).data('indice')) < ($(a).data('indice')) ? 1 : -1 :
					        ($(b).data('pagenum')) < ($(a).data('pagenum')) ? 1 : -1;
					}).appendTo('#errori-ortografici-list');
			    } else {
			    	$('#loading-errori-ortografici').html('Trovati 1000 possibili errori in ' + maxIndexPages + ' indici, ricerca interrotta per troppi risultati:');
			    }
		    } else {
		    	console.log("Nessun pagenum trovato");
		    	// console.log("Nessun pagenum trovato in " + indexWithoutNs + " pagine " + fromPageNum + "-" + toPageNum);
		    }
		}
	};
	
	parsePages = function(lastPageNum, fromPageNum, mode, indexWithoutNs, q0List, puretext, startTime, singlePage) {
		var isLast = true;
		var toPageNum = lastPageNum;
		if (toPageNum - fromPageNum >= pagesToLoad) {
			toPageNum = fromPageNum + pagesToLoad - 1;
			isLast = false;
		}
		console.log("Load pure text from " + indexWithoutNs + " pages " + fromPageNum + "-" + toPageNum);
		var wtext = '<' + 'pages index="' + indexWithoutNs + '" from="' + fromPageNum + '" to="' + toPageNum + '" exclude="' + q0List + '"/>';
		if (mode == 'spelling') {
			wtext = "";
			for (p = fromPageNum; p <= toPageNum; p++) {
				wtext += '<' + 'pages index="' + indexWithoutNs + '" from="' + p + '" to="' + p + '" exclude="' + q0List + '"/><references/>';
			}
		}
		
		api.post({
			action: 'parse',
			text: wtext,
			prop: 'text',
			contentmodel: 'wikitext',
			disablelimitreport: 1,
			format: 'json',
		}).done(function (data, textStatus, jqXHR) {
			if (data.parse === undefined || data.parse.text['*'] === undefined) {
				$('.errori-ortografici-box-main').html('Errore nella ricerca');
				return;
			}
			var html = data.parse.text['*'];
			var div = document.createElement("div");
			
			// ripuliamo l'html da tutti gli elementi "estranei" al testo
			div.innerHTML = html.replaceAll("<br />", " ")
				.replaceAll("<sup>", " ^ <sup>")  // marcatore temporaneo per il testo in apice
				.replaceAll("	", " ") // tab
				.replaceAll("  ", " ").replaceAll("  ", " "); // spazi ripetuti
			$(div).find('style, .eco, .linkModifica, .imgCaption, .numeroriga, a.new[title^=Pagina], .mwe-math-element').remove();
			
			// in spelling mode, show page numbers from the file
			if (mode == 'spelling') {
				$(div).find('.numeropagina').each(function(ind) {
					$(this).html('[p. ' + $(this).data('pagenum') + ']');
				});
			}
			
			$(div).find('.reference').each(function(ind) {
				$(this).html(' (' + $(this).text() + ')');
			});
			$(div).find('[style="font-variant:small-caps"]').each(function(ind) {
				$(this).text($(this).text().toUpperCase());
			});
			
			// this removes any remaining html tags
			text = div.textContent || div.innerText || "";
			puretext += text;
			
			if (mode == 'spelling') {
				for (i = 0; i < regexList.length; i++) {
					checkForErrors(text, regexList[i], indexWithoutNs, false);
				}
			}
			
			if (!isLast) {
				fromPageNum += pagesToLoad;
				parsePages(lastPageNum, fromPageNum, mode, indexWithoutNs, q0List, puretext, startTime, singlePage);
			} else {
				duration = (Date.now() - startTime) / 1000;
				console.log("Pure text loaded from all pages in " + duration + " seconds");
				var noteNumber = 0;
				puretext = puretext.replace(/↑/g, function() {
					noteNumber++;
					return noteNumber + ".";
				});
				puretext = puretext.replaceAll(" ^ ", "");
	
				if (mode == 'download') {
					puretext = puretext.replace(/\n +\[/g, '\n[').replace(/ +\[/g, ' [');
					
					var j = document.createElement("a");
					j.download = indexWithoutNs.replace(/djvu|pdf/, 'txt');
					j.href = URL.createObjectURL(new Blob([puretext]));
					j.click();
				} else if (mode == 'spelling') {
					
					var total = $('#errori-ortografici-list li').length;
					if (singlePage) {
						singlePageText = puretext;
						singleIndexWithoutNs = indexWithoutNs;
						var link = document.createElement("a");
						link.id = 'downloadTextForSpelling';
						link.classList.add("blue");
						link.download = indexWithoutNs.replace(/djvu|pdf/, 'txt');
						link.href = URL.createObjectURL(new Blob([puretext]));
						link.title = "Scarica il puro testo usato per la ricerca degli errori";
						link.appendChild(document.createTextNode("Scarica il testo puro"));
						$('#errori-ortografici-help').after(link);
						
						$('#downloadTextForSpelling').after('<button class="btn blue" id="openSearchRegex">Cerca...</button>');
						$('#openSearchRegex').click(function() {
							$('#errori-ortografici-list').empty();
							$('#loading-errori-ortografici').hide();
							$('#errori-ortografici-list').before('<div id="searchRegexBox"><label>Testo o regex: </label>' +
								'<input type="text" id="freeSearch"></div><span id="searchRegexResults"></span>');
							$('#freeSearch').focus();
							$('#openSearchRegex').attr('disabled', 'true');
							
							$('#freeSearch').keyup(function(e) {
								$('#invalidRegexMsg').remove();
								$('#searchRegexResults').empty();
								var reg = $(this).val();
								var flags = 'g';
								var regFlags = reg.match(/\/([gim]*)$/);
								if (regFlags != undefined && regFlags.length > 1)
									flags = regFlags[1];
								
								reg = reg.replace(/^\//, '').replace(/\/g?i?$/, '');
								if (reg.length > 0) {
									try {
										var custRegex = [ new RegExp(reg, flags), '' ];
										$('#errori-ortografici-list').empty();
										checkForErrors(singlePageText, custRegex, singleIndexWithoutNs, true);
									} catch (e) {
										$('#searchRegexBox').after('<span id="invalidRegexMsg" class="alert">Regex non valida</span>');
									}
								}
							});
						});
						
						if (total == 0) {
							$('#loading-errori-ortografici').html('Caricamento terminato. Nessun errore trovato.');
						} else if (total == 1) {
							$('#loading-errori-ortografici').html('Caricamento terminato. Trovato un possibile errore:');
						} else {
							$('#loading-errori-ortografici').html('Caricamento terminato. Trovati ' + total + ' possibili errori:');
						}
					} else {
						$('#loading-errori-ortografici').html('Trovati ' + total + ' possibili errori in ' + maxIndexPages + ' indici:');
					}
				}
			}
		});
	};
	
	mw.util.addPortletLink(
		'p-tb',
		'#',
		'Cerca errori ortografici',
		't-erroriOrtograficiRiletti',
		"Cerca errori ortografici negli indici di una data categoria"
	);
	
	startSearch = function(cat) {
		api.get({
			action: 'query',
			format: 'json',
			list: 'categorymembers',
			cmtype: 'page',
			cmlimit: 5000,
			cmnamespace: "0|110",
			cmtitle: 'Categoria:' + cat
		}).done(function (data) {
			if (data.query) {
				var members = data.query.categorymembers;
				if (members.length === 0) {
					$('#loading-errori-ortografici').html('Nessun indice trovato');
				} else {
					var titles = [];
					for (i = 0; i < members.length; i++) {
						titles.push(members[i].title); 
					}
					titles.sort(function (a, b) {
						return Math.random() - 0.5;
					});
					if (maxIndexPages > titles.length)
						maxIndexPages = titles.length;
						
					titles = titles.slice(0, maxIndexPages);
					titles.sort();
					for (j = 0; j < titles.length; j++) {
						if (!titles[j].startsWith("Indice:")) {
							api.get({
								action: 'query',
								format: 'json',
								list: 'backlinks',
								bltitle: titles[j],
								blnamespace: 110,
								bllimit: 500
							}).done(function (data) {
								if (data.query) {
									var members = data.query.backlinks;
									for (k = 0; k < members.length; k++) {
										getPureText('spelling', members[k].title);
									}
								}
							});
						} else {
							console.log("Cerca errori ortografici in " + titles[j]);
							getPureText('spelling', titles[j]);
						}
					}
				}
			}
		});
	};
	
	$('#t-erroriOrtograficiRiletti').click(function(e) {
		e.preventDefault();
		$('.errori-ortografici-box').remove();
		openBox();
		$('#loading-errori-ortografici').hide();
		$('#loading-errori-ortografici').before('<div id="errori-ortografici-params"></div>');
		$('#errori-ortografici-params').append('<div>Cerca errori ortografici in un numero massimo di indici presi a caso nella categoria indicata');
		$('#errori-ortografici-params').append('<div><label>Categoria: </label><input type="text" id="errori-ortografici-cat" value="Pagine indice SAL 100%"/></div>');
		$('#errori-ortografici-params').append('<div><label>Numero di indici: </label><input type="number" id="errori-ortografici-max" value="20" style="text-align: right"/></div>');
		$('#errori-ortografici-params').append('<div><button id="errori-ortografici-search" class="btn blue">Cerca</button></div>');
		$('#errori-ortografici-params').append('<div class="small-label">La categoria deve contenere pagine indice o ns0, es.: Romanzi, Libri di Dante Alighieri, Pagine indice SAL 75%</div>');
		
		$('#errori-ortografici-search').click(function(e) {
			var cat = $('#errori-ortografici-cat').val().replace(/[Cc]ategor(ia|y):/, '');
			cat = cat.charAt(0).toUpperCase() + cat.slice(1);
			maxIndexPages = $('#errori-ortografici-max').val();
			$('#loading-errori-ortografici').text('Caricamento in corso...').show();
			$('#errori-ortografici-list').empty();
			startSearch(cat);
		});
	});
	
	loadIndexButtons = function() {
		$('#downloadPureText, #cercaErroriOrtografici, .errori-ortografici-box').remove();
		$('.exportLinkContainer').append('<div class="exportLink"><a id="downloadPureText" class="external text" ' + 
			'title="Scarica il solo testo di tutte le pagine, senza copertina e senza nessuna formattazione"><span>' +
			'<img src="https://upload.wikimedia.org/wikipedia/commons/3/36/16x16-icon-w-txt.png"></span>Testo puro</a></div>');
		$('#downloadPureText').click(function() {
			getPureText('download');
		});
		$('#indiceHeader').prepend('<a id="cercaErroriOrtografici" class="blue" title="Cerca errori ortografici in questo indice">Cerca errori ortografici</a>');
		$('#cercaErroriOrtografici').click(function() {
			$('.errori-ortografici-box').remove();
			
			// aggiungo alla lista regex le eventuali regex utente
			mw.loader.getScript('https://it.wikisource.org/w/index.php?title=Utente:' + mw.config.get("wgUserName") + '/customRegex.js&action=raw&ctype=text/javascript')
			.then(function () {
				regexList = regex.concat(customRegex);
				openBox();
				getPureText('spelling');
		    }, function (e) {
		    	openBox();
		        getPureText('spelling');
		    });
		});
	};
	
	if (mw.config.get('wgCanonicalNamespace') == 'Index') {

		// carica regex dalla pagina di discussione dell'indice
		var talkPage = 'Index_talk:' + mw.config.get('wgPageName').replace('Indice:', '');
		api.get({
			action: 'parse',
			format: 'json',
			page: talkPage,
			prop: 'sections'
		}).always(function (data) {
			var found = false;
			if (data.parse && data.parse.sections) {
				var sections = data.parse.sections;
				for (var i = 0; i < sections.length; i++) {
					if (sections[i].line == 'ErroriOrtografici') {
						found = true;
						api.get({
							action: 'query',
							prop: 'revisions',
							titles: talkPage,
							rvsection: sections[i].index,
							rvprop: 'content',
							rvslots: 'main',
							format: 'json',
						}).done(function (data) {
							$.each(data.query.pages, function(k, v) {
							    var sectionText = (v.revisions['0'].slots.main['*']).replace(/==.*?==/g, '');
							    //console.log(sectionText);
							    
							    // remove html tags from section text
							    var div = document.createElement("div");
							    div.innerHTML = sectionText;
								jsonText = div.textContent || div.innerText || "";
								
							    var sectionObj = JSON.parse(jsonText);
							    operaExceptions = sectionObj.eccezioni;
							    console.log('Eccezioni opera-specifiche caricate dalla sezione ErroriOrtografici nella pagina di discussione: ' + operaExceptions);
							    loadIndexButtons();
							});
						});
					}
				}
			}
			
			if (!found) {
				console.log('Non è presente una sezione ErroriOrtografici nella pagina di discussione');
				loadIndexButtons();
			}
		});
	}
});