MediaWiki:Gadget-Erori-comuni.js
Ocio: Daspò ver salvà, podaria esare neçesario snetare ła cache dal propio navegadore web par vedare i canbiamenti.
- Firefox / Safari: tegner strucà el boton de łe letare grande Shift e schiciare sora Ricarga, o se nò struca Ctrl-F5 o Ctrl-R (⌘-R so Mac)
- Google Chrome: strucare Ctrl-Shift-R (⌘-Shift-R so on Mac)
- Internet Explorer / Edge: tegner strucà el boton Ctrl e schiciare so Ajorna, o sinò Ctrl-F5
- Opera: Va in tel Menu → Inpostasion (Opera → Prefarense so on Mac) e pò in Privacy & sicuresa → Sneta dati del navegadore → Imajini e file in te ła cache.
/* Adatà da fr.wikisource.org/wiki/MediaWiki:Gadget-Erreurs-communes.js*/
/*
* Permet de montrer dans un texte les erreurs les plus communes.
*
* Auteur: Phe
*
* TODO:
*
* Permettre des auto-corrections.
*
* Le support en mode édition est très expérimental, il manque un bouton refresh à
* la liste des erreurs pour éviter d'avoir à faire un preview quand on a corrigé.
* Certaines erreurs ne seront visible que dans le html, « . <minuscule> » par
* exemple s'il y a y un \n dans le wikicode entre le . et la minuscule.
* Le wikicode n'est pas strippé ce qui doit produire des tas de faux positifs.
*
* En mode édition cliquer sur un lien se positionne toujours sur la première
* erreur.
*
* En mode édition il arrive fréquemment qu'une erreur détecté ne puisse
* être localisé dans la boîte d'édition.
*
* Le contenu d'une textarea est un nœud texte qui est splitter en plusieurs
* nœud html, le browser à l'air assez futé pour comprendre qu'un textarea ne
* peut contenir qu'un nœud texte et ignore les trucs insérer mais ça ne
* va pas du tout (incompatibilité avec le gadget auteur form par exemple -->
* ns:104 ignoré pour l'instant).
*
*/
/*
* http://stackoverflow.com/questions/5458655/jquery-scroll-textarea-to-given-position
*
* Construit un div avec la même font que la textarea pouvoir calculer la position de scroll.
*/
jQuery.fn.scrollToText = function(search) {
var text = $(this).text();
var charNo = text.indexOf(search);
var anch = '<span id="anch"></span>';
text = text.substring(0, charNo) + anch + text.substring(charNo);
var copyDiv = $('<div></div>')
.append(text.replace(/\n/g, '<br />'))
.css('width', $(this).innerWidth()) // width without scrollbar
.css('font-size', $(this).css('font-size'))
.css('font-family', $(this).css('font-family'))
.css('padding', $(this).css('padding'));
copyDiv.insertAfter($(this));
var pos = copyDiv.find('SPAN#anch').offset().top - copyDiv.find('SPAN#anch').closest('DIV').offset().top;
pos = pos - Math.round($(this).innerHeight() / 2);
$(this).scrollTop(pos);
copyDiv.remove();
};
select_multiple_text = {
precompile_regexp : function (search) {
var temp = [];
for (var i in search)
temp.push(new RegExp("(" + search[i] + ")", "g"));
return temp;
},
build_popup : function() {
var html = "";
$('span.erori-comuni').each(function (index, el) {
//$(this).removeAttr('id');
html += "<li><a href='javascript:select_multiple_text.scroll_to_pos(" + index + ");'>" + $(this).text() + "</a></li>";
$(this).attr('id', 'Err-' + index);
});
return html;
},
last_scroll_pos : 0,
scroll_to_pos : function(index) {
var found = false;
if ($.inArray(mw.config.get('wgAction'), [ 'submit', 'edit' ]) != -1) {
var textbox = document.getElementById("wpTextbox1");
if (textbox) {
var text = $("#Err-" + index).text();
var pos = textbox.value.indexOf(text);
if (pos != -1) {
textbox.selectionStart = pos;
textbox.selectionEnd = pos + text.length;
textbox.focus();
$('#wpTextbox1').scrollToText(text);
found = true;
}
}
}
if (!found) {
$("#Err-" + select_multiple_text.last_scroll_pos).css("background-color", "");
window.location.hash = "#Err-" + index;
$("#Err-" + index).css("background-color", "#00FF00");
select_multiple_text.last_scroll_pos = index;
// index * 2 + 1 is voodoo making assumption on the html struct of the
// popup, see build_popup(), there is surely a simpler and safer way.
$('#err-communes-popup').find('*:eq(' + (index * 2 + 1) + ')').focus();
}
},
close_popup : function() {
$("#err_summary").remove();
return;
},
open_popup : function() {
if ($("#err_summary").remove().length)
return;
var elt = $("<div id='err_summary'></div>");
elt.css({
"position" : "fixed",
"min-width" : "16em",
"max-width" : "35em",
"max-height" : "35em",
"right" : "0.5em",
"background-color" : "#FFFFFF",
"z-index" : 1,
"border" : "1px solid",
"padding" : "8px"
});
var str = '<div style="float:right;"><a href="javascript:select_multiple_text.close_popup();"><img src="//upload.wikimedia.org/wikipedia/commons/9/97/WikEd_close.png"/></a></div><h4>'+ 'Erreur(s) possible' + ' :</h4><div style="overflow:auto;min-width:16em;max-width:35em;max-height:32em;"><ul id="err-communes-popup">' + select_multiple_text.build_popup() + '</ul></div>';
elt.html(str);
$("#bodyContent").prepend(elt);
},
match : function (text, regexp) {
var m = text.match(regexp);
if (m) {
var start_match = text.search(regexp);
var end_match = start_match + m[0].length;
return [ start_match, end_match, m[0] ];
}
return null;
},
change_text_node : function(el, search, first) {
for (var cur = first; cur < search.length; ++cur) {
var match = this.match(el.nodeValue, search[cur]);
if (match) {
var tail = $(el).clone()[0];
el.nodeValue = el.nodeValue.substring(0, match[0]);
tail.nodeValue = tail.nodeValue.substring(match[1]);
// FIXME: how to setup the text part of the span w/o injecting it in html ?
$(el).after(tail).after($("<span class='erori-comuni'>" + match[2] + "</span>"));
select_multiple_text.change_text_node(el, search, cur + 1);
select_multiple_text.change_text_node(tail, search, cur);
}
}
},
match_text : function (text, search) {
// Il faut faire ressembler le wikicode à du html, il manque plein de
// truc encore...
text = text.replace(/'''/g, "");
text = text.replace(/''/g, "");
// Kludge
text = text.replace(/\n\n/g, "#<foo>#");
text = text.replace(/\n/g, " ");
text = text.replace(/#<foo>#/g, "\n\n");
// Indispensable pour éviter un timeout du script sur une grosse page contenant
// beaucoup de wikicode.
var new_text = '';
var last_match = 0;
var splitter = new RegExp("<math>.*</math>|<[a-zA-z0-9 =\"']>|[</[a-zA-z0-9 =\"']+>|style=\".*\"| |—|<!--.*-->|\n:[:]*|\n;[;]*|[[][[].*]]", "gm");
while ((result = splitter.exec(text)) != null) {
new_text += text.slice(last_match, splitter.lastIndex - result[0].length);
for (var i = 0; i < result[0].length; ++i)
new_text += ' ';
last_match = splitter.lastIndex;
}
new_text += text.slice(last_match);
text = new_text;
// Les nœud invisible servent à stocker à stocker les erreurs trouvés de
// façon à réutiliser le même code que lorsque wgAction == submit.
var $node = $('#bodyContent');
for (var i = 0; i < search.length; ++i) {
var pos = 0;
while ((match = this.match(text.slice(pos), search[i])) != null) {
pos += match[1];
$node.append($("<span class='erori-comuni' style='display:none;'>" + match[2] + "</span>"));
}
}
},
// Predicate to filter page we act on based upon a user filter and some other criteria.
filter_page : function(user_filter) {
if ($.inArray(mw.config.get("wgAction"), [ 'view', 'submit', 'edit' ]) == -1)
return false;
if (!user_filter.test(mw.config.get("wgPageName")))
return false;
if (/\.(css|js)$/.test(mw.config.get("wgPageName")))
return false;
if (/^Wikisource:/.test(mw.config.get("wgPageName")))
return false;
if ($("#wikiDiff").length)
return false;
/* FIXME: filtre les cats à cause de Page:pagename et Livre:livre.djvu
* mais c'est trop drastique comme solution */
if (mw.config.get("wgNamespaceNumber") == 14)
return false;
if (mw.config.get("wgNamespaceNumber") == 6)
return false;
if (mw.config.get("wgNamespaceNumber") == 112)
return false;
if (mw.config.get("wgNamespaceNumber") == 828)
return false;
if (mw.config.get("wgNamespaceNumber") == 2600) // Topic ou Sujet
return false;
if (mw.config.get("wgNamespaceNumber") == 2 && mw.config.get("wgPageName").indexOf('/') == -1)
return false;
if (mw.config.get("wgNamespaceNumber") % 2 != 0)
return false;
/* Incompatibilité avec le gadget auteur form, voir plus haut. */
if (mw.config.get("wgNamespaceNumber") == 102 && mw.config.get("wgAction") == 'edit')
return false;
return true;
},
filter_node : function() {
if ($(this).parent().hasClass('erori-comuni'))
return false;
return this.nodeType == 3;
},
get_text_nodes : function () {
var content_id = "#bodyContent";
if ($("#wikiPreview").length)
content_id = "#wikiPreview";
// TODO: Bencher sur //fr.wikisource.org/wiki/L’Encyclopédie/Volume_1
// ou tout autre page qui contient un grand nombre de nœud.
return $(content_id)
.find("*")
.not($(".no_erreurs_communes *"))
.not($(".diff *"))
.not($(".printfooter *"))
.not($(".previewnote *"))
.not($("#modernisations *"))
.not($("#authorityControl *"))
.not($("#dynamic_links *"))
.not($("#contentSub *"))
.not($("#ws-data *"))
.not($("pre"))
.not($("script"))
.not($("style")) // TemplateStyles
.not($(".mwe-math-element *"))
.not($(":not(:lang(fr))"))
.contents()
.filter(select_multiple_text.filter_node);
},
portlet_link_added : false,
exec : function(user_filter, search) {
if (!select_multiple_text.filter_page(user_filter))
return;
search = select_multiple_text.precompile_regexp(search);
if (mw.config.get('wgAction') == 'edit') {
if ($('#wpTextbox1').length) {
this.match_text($('#wpTextbox1')[0].value, search);
}
} else {
var text_nodes = select_multiple_text.get_text_nodes();
$.each(text_nodes, function(i, el) {
select_multiple_text.change_text_node(el, search, 0);
});
}
var error_count = $('span.erori-comuni').length;
if (error_count) {
if (!select_multiple_text.portlet_link_added) {
mw.loader.using('mediawiki.util', function() {
mw.util.addPortletLink ("p-tb", "javascript:select_multiple_text.open_popup();",
"", "option-commons-errors", "");
});
}
$('#option-commons-errors a').text('Erreur(s) possible' + " (" + error_count + ")");
select_multiple_text.portlet_link_added = true;
}
},
default_select : function() {
/* il faut une var qui définissent une espace, sécable, non sécable
* etc. et qui fonctionne avec les entités html comme
*/
var char_min = 'a-zéèàùâêîôûŷäëïöüÿçœæſñ';
var char_maj = 'A-ZÉÈÀÂÙÊÎÔÛŶÄËÏÖÏŸÇŒÆÑ';
var char = char_min + char_maj;
var bw = '([^' + char + ']|^)';
var ew = '([^' + char + ']|$)';
var ch = '[' + char + ']';
select_multiple_text.exec(/.*/,
[
"[^.][.][.][.](?![.])",
"'", "‘",
/* devrait inclure \\. mais match etc., et toutes les abbrevs, trop de
* faux positifs */
"[!:,;?][,;]+",
"[" + char_min + "][!?:;]",
"[!?;:.,][" + char + "]",
"[ ][\\.,]",
"[\\.?!] 11[^0-9]",
"[0-9]" + ch,
ch + "[0-9]",
"1e[^r]", "[!1][a]",
// caractères isolés non existant en français.
bw + "[ù]" + ew,
"[íì~fffiflffifflſtst]",
bw + "carie",
bw + "entant",
"celte[^s,.]",
bw + "clans",
"\\. Gela",
"\\. Gomme",
bw + "[mM]ôme" + ew,
bw + "[mM]émo" + ew,
bw + "[DdcCLlNnSsTtMmNn]o" + '([^' + char + '-' + ']|$)',
bw + "[CcLlSsTtMm]os" + ew,
bw + "quo" + ew,
"[ \n-]i[[t][ ,.]",
/* mot d'au moins 3 lettres suivant par un . et sans majuscule */
"[" + char_min + "-][" + char_min + "][^0-9A-Zpvcgm°.][.] [" + char_min + "]",
/* la même chose pour les mots de deux lettres les plus courant */
"(ma|ta|sa|ce|se|ni|va|pu|et|le|la|de|du|un|te|je|tu|il|me|ne|ou|où|ok|à|y|a)[.] [" + char_min + "]",
"[ ][bB][éè]te[, ]",
bw + "tète" + ew,
"(^A | A )",
"([^vmhp]\\. |[?!:] |^)(II|ll)(?!([Ie.]|$))",
"1’" + ch,
"(\\. |^)(Tun|Tune)" + ew,
"est-a-dire",
"[^ \n]—",
"—[^ \n]",
"[ ]-",
"-[ ]",
"[ ]’",
"’[ ]",
]);
}
};
$(document).ready(select_multiple_text.default_select);