Unnaschied vunde Gschischde vun "Middawaida:YMS/eagleeye.js"
Inhalt gelöscht Inhalt hinzugefügt
YMS (Dischbediere | Baidräsch) Still issues with aborting and collapsing |
YMS (Dischbediere | Baidräsch) Added rule editor (incl. copy template generation, auto testing), improved result display (incl. option to display all results), introduced German localisation, merged Abort and Search button, reorganized option parameters (namespace option now for all 3) |
||
Zail 2:
* EagleEye
* Tool for searching, spotting and correcting hard-to-sport errors
* For
* <nowiki> ([[bugzilla:8761]])
*/
Zail 8:
// Options and Ruleset
var rules = getOption("eeRules", []); // The rule set
var lang = getOption("eeLang", getDefaultLang(["en", "de"])); // Language (currently supported: de, en; default: user language or project language or en, whichever first is available)
var
var
var
var markerPrefix = getOption("eeMarkerPrefix", "ee_"); // Prefix for markers (e.g. "ee_" will result in markers like "ee_Doppelwort", may be set to "" for no prefix)
var markerStyle = getOption("eeMarkerStyle", "background-color: #FF9191;"); // CSS style for the marker highlighting (more can be defined for span.eeMarker in user CSS)
var chunkSize = getOption("eeScannerChunkSize", 10000000); // The chunk size for the database scanner (too low values will fail [depends on database] or cause bad performance, too high values may cause bad performance or even crashes)
var listAll = getOption("eeScannerListAll", false); // Whether the scanner should list all matches for a page instead of only the first one
var scannerPage = getOption("eeScannerPage", mw.config.get("wgFormattedNamespaces")[2] + ":YMS/EagleEye"); // The page that will trigger the database scanner
var ignoreRedirects = true; // With current scanner functionality, it's pointless to allow redirects
// Labels
var labels = {
lblAbort: { en: "Abort scan", de: "Scan abbrechen" },
lblChunkSize: { en: "Chunk size (in bytes)", de: "Chunk-Größe (in Byte)" },
lblCopyTemplateLong: { en: "Copy Template for ruleset file", de: "Kopiervorlage für Ruleset-Datei" },
lblInstalled: { en: "Script already is installed and active.", de: "Das Skript ist bereits installiert und aktiv." },
lblListAll: { en: "List all matches (instead of only the first one for every page)", de: "Alle Ergebnisse auflisten (statt nur dem ersten pro Seite)" },
lblOptions: { en: "Options", de: "Optionen" },
lblReplace: { en: "Replace", de: "Ersetze" },
lblRule: { en: "Rule", de: "Regel" },
lblRules: { en: "Rules", de: "Regeln" },
lblScanDump: { en: "Scan dump", de: "Dump scannen" },
lblSearch: { en: "Search", de: "Suche" },
lblSelectDump: { en: "Select database dump file", de: "Datenbank-Dump-Datei wählen" },
lblSkip: { en: "Skip", de: "Überspringen" },
lblTest: { en: "Test", de: "Test" },
lblTitle: { en: "Title", de: "Titel" },
lblUseSkiplist: { en: "Use Skiplist", de: "Skiplist verwenden" },
};
// Internal variables
var SCANNER = 0;
var MARKER = 1;
var CORRECTOR = 2;
var base;
var start = 0;
Zeile 58 ⟶ 71:
var nextText = "";
var results;
var subResults;
var startTime;
var
Zeile 69 ⟶ 83:
s = s.replace(new RegExp("\\{" + i + "\\}", "gm"), arguments[i]);
}
return s;
};
// Get default language (user language, if available, else project language, if available, else first defined language)
function getDefaultLang(supportedLanguages) {
if ($.inArray(mw.config.get("wgUserLanguage"), supportedLanguages) != -1) {
return mw.config.get("wgUserLanguage");
} else if ($.inArray(mw.config.get("wgContentLanguage"), supportedLanguages) != -1) {
return mw.config.get("wgContentLanguage");
} else {
return supportedLanguages[0];
}
}
// Internationalisation of a label
function txt(label) {
if (labels[label] == null || labels[label][lang] == null) {
return txt("
}
return labels[label][lang];
}
// Load a user-defined configuration variable or the given default
function getOption(name, defaultvalue) {
return (typeof window[name] === "undefined") ? defaultvalue : window[name];
}
// Sets text of progress display
function setProgress(text) {
$("#eeProgress").text(text);
}
// Sets text of status section
function setStatus(text) {
Zeile 102 ⟶ 122:
}
// Add
function
resultList = searchByRules(object);
if (resultList.results
for (var rule in resultList.results) {
count += resultList.results[rule].length;
}
$("#eeResultTable").append($("<tr />", { id: "eeResult_" + subResults, class: "eeResultTableDataLine" }));
$("#eeResult_" + subResults).append($("<td />", { class: "eeResultTableTitleColumn", rowspan: count }).append('[[<a href="' + base + encodeURI(resultList.title) + '">' + resultList.title + '</a>]]'));
var first = true;
for (var rule in resultList.results) {
if (! first) {
$("#eeResultTable").append($("<tr />", { id: "eeResult_" + subResults, class: "eeResultTableDataLine" }));
}
first = false;
$("#eeResult_" + subResults).append($("<td />", { class: "eeResultTableRuleColumn", rowspan: resultList.results[rule].length }).append(rules[rule].name));
for (var i = 0; i < resultList.results[rule].length; i++) {
if (i != 0) {
$("#eeResultTable").append($("<tr />", { id: "eeResult_" + subResults, class: "eeResultTableDataLine" }));
}
$("#eeResult_" + subResults).append($("<td />", { class: "eeResultTableMatchColumn" }).append($("<textarea />").html(resultList.results[rule][i]).html()));
subResults++;
}
}
results++;
}
}
// Iterate all rules and match given text to it
function searchByRules(object) {
var resultList = { title: object.find("title").text(), results: [] };
var dummyRegExp = new RegExp("").source;
for (var i = 0; i < rules.length; i++) {
if (rules[i].inactive == null || rules[i].inactive == false) {
// Match rule if not inactive
var match = object.find("text").text().match(new RegExp(rules[i].match.source, "g"));
if (match != null) {
// Check results for skiplist match
for (var j = 0; j < match.length; j++) {
if (! useSkiplist[SCANNER] || rules[i].skip === undefined || rules[i].skip.source == dummyRegExp || ! match[j].match(rules[i].skip)) {
} else {
resultList.results[i].push(match[j]);
}
if (! listAll) {
return resultList;
}
}
}
Zeile 127 ⟶ 188:
}
}
return resultList;
}
// Validate a single RegEx rule
function checkRule(i) {
if (rules[i].match === null) {
setStatus(txt("statRuleUndefined").format(i, rules[i].name));
return false;
}
try {
if (rules[i].test != null && rules[i].test.length > 0) {
// Check standard test case
if (rules[i].test.match(rules[i].match) === null) {
setStatus(txt("statRuleFailsTest").format(i, rules[i].name));
return false;
}
} else {
// Perform dummy test to check formal validity
"dummy".match(rules[i].match);
}
} catch (e) {
setStatus(txt("statRuleInvalid").format(i, rules[i].name, e));
return false;
}
return true;
}
// Validate RegEx rule set
function checkRules() {
for (var i = 0; i < rules.length; i++) {
if (! checkRule(i)) {
return false;
}
}
return true;
}
// Edit window processing
function scanEditWindow() {
Zeile 167 ⟶ 235:
for (var i = 0; i < rules.length; i++) {
if (
if (! changed) {
if ($("#wpTextbox1").text().match(rules[i].match) != null) { changed = true;
}
}
$("#wpTextbox1").text($("#wpTextbox1").text().replace(new RegExp(rules[i].match.source, "g"), rules[i].replace));
}
}
if (changed && (! a || ! a.nodeType || a.nodeName == "IMG")) {
$((a && a.nodeType) ? a : "img[rel=EagleEye]").css("backgroundColor", changed ? "#DEF740" : "");
Zeile 181 ⟶ 251:
};
// Corrector: Add button to edit mode
function addButton() {
$("#wpTextbox1").wikiEditor("addToToolbar", {
Zeile 187 ⟶ 257:
group: "format",
tools: {
label: txt("
type: "button",
icon: "//upload.wikimedia.org/wikipedia/commons/thumb/f/fb/PR_icon.png/22px-PR_icon.png",
action: {
type: "callback",
execute: function() {
scanEditWindow();
}
Zeile 202 ⟶ 272:
}
// Marker: Mark findings in article view
function markView() {
$("#mw-content-text").children(":not(.diff)").each(function() {
Zeile 214 ⟶ 284:
});
}
// Add a collapsible section to the HTML
function addSection(sectionID, bodyID, sectionContent, bodyContent, collapsed) {
$("#mw-content-text").append($("<div/>", { id: sectionID, class: "mw-collapsible eeSection" }).addClass((collapsed) ? "mw-collapsed" : "").append("<b>" + sectionContent + "</b>").append($("<div />", { id: bodyID, class: "mw-collapsible-content" }).append(bodyContent)));
}
// Get the settings for a certain rule from user's input
function applyRuleSettingsFromUI(i) {
rules[i].inactive = ! $("#eeRuleCB_" + i).attr("checked");
rules[i].name = $("#eeRuleName_" + i).val();
rules[i].match = new RegExp($("#eeRuleMatch_" + i).val());
rules[i].skip = new RegExp($("#eeRuleSkip_" + i).val());
rules[i].replace = $("#eeRuleReplace_" + i).val();
rules[i].test = $("#eeRuleTest_" + i).val();
rules[i].note = $("#eeRuleNotes_" + i).val();
}
// Get rules and other settings from user's input
function applySettingsFromUI() {
// Rules
for (var i = 0; i < rules.length; i++) {
applyRuleSettingsFromUI(i);
}
// Options
useSkiplist[SCANNER] = $("#eeOptionCB_useSkiplist").attr("checked");
listAll = $("#eeOptionCB_listAll").attr("checked");
chunkSize = Number($("#eeOptionCB_chunkSize").val());
if (isNaN(chunkSize) || chunkSize <= 0) {
setStatus(txt("statInvalidChunkSize"));
return;
}
// Namespaces
namespaces[SCANNER] = [];
$("input[id^=eeNamespaceCB_]").each(function() {
if ($(this).attr("checked")) {
namespaces[SCANNER].push(Number($(this).attr("id").substring($(this).attr("id").indexOf("_") + 1)));
}
});
}
// Add a rule editor for the given line
function addRuleEditor(i) {
$("#eeRuleEditorTable").append($("<tr />", { id: "eeRuleEditor_" + i, class: "eeRuleEditorTableDataLine" }));
$("#
$("#eeRuleEditor_" + i).append($("<td />", { class: "eeRuleEditorTableNameColumn" }).append($("<input />", { type: "text", id: "eeRuleName_" + i, value: rules[i].name }).css("width", "100%")));
$("#eeRuleEditor_" + i).append($("<td />", { class: "eeRuleEditorTableMatchColumn" }).append($("<input />", { type: "text", id: "eeRuleMatch_" + i, value: (rules[i].match === undefined) ? "" : rules[i].match.source }).css("width", "100%")));
$("#eeRuleEditor_" + i).append($("<td />", { class: "eeRuleEditorTableSkipColumn" }).append($("<input />", { type: "text", id: "eeRuleSkip_" + i, value: (rules[i].skip === undefined) ? "" : rules[i].skip.source }).css("width", "100%")));
$("#eeRuleEditor_" + i).append($("<td />", { class: "eeRuleEditorTableReplaceColumn" }).append($("<input />", { type: "text", id: "eeRuleReplace_" + i, value: rules[i].replace }).css("width", "100%")));
$("#eeRuleEditor_" + i).append($("<td />", { class: "eeRuleEditorTableTestColumn" }).append($("<input />", { type: "text", id: "eeRuleTest_" + i, value: rules[i].test }).css("width", "100%")));
$("#eeRuleEditor_" + i).append($("<td />", { class: "eeRuleEditorTableNotesColumn" }).append($("<input />", { type: "text", id: "eeRuleNotes_" + i, value: rules[i].note }).css("width", "100%")));
$("#eeRuleEditor_" + i).append($("<td />", { class: "eeRuleEditorTableCopyColumn" }).append($("<input />", { type: "button", id: "eeRuleCopy_" + i, value: txt("lblCopyTemplate") })));
// Check test on relevant changes
$("#eeRuleMatch_" + i + ",#eeRuleTest_" + i).change(function() {
applyRuleSettingsFromUI(i);
$("#eeRuleTest_" + i).css("background-color", (checkRule(i)) ? "#88FF88" : "#FF8888");
}).change();
// Create copy template on request
$("#eeRuleCopy_" + i).click(function() {
applyRuleSettingsFromUI(i);
$("<p/>", { title: txt("lblCopyTemplateLong") }).append('{<br />name: "{0}",<br />match: {1},<br />replace: "{2}",<br />skip: {3},<br />note: "{4}",<br />test: "{5}",<br />inactive: {6}<br />}'.format(rules[i].name, rules[i].match, rules[i].replace, rules[i].skip, rules[i].note, rules[i].test, rules[i].inactive)).dialog();
});
}
// Sets the running state and changes start/abort button's label and behaviour
function setRunning(run) {
running = run;
if (running) {
$("#eeSearch").val(txt("lblAbort"));
} else {
$("#eeSearch").val(txt("lblScanDump"));
}
}
// Add the GUI elements for the scanner
function loadScannerUI() {
Zeile 234 ⟶ 371:
$("#eeInstallation").addClass("mw-collapsed");
}
// Rules
var table = $("<table />", { id: "eeRuleEditorTable", class: "eeRuleEditorTable", width: "100%" });
var header = $("<tr />", { id: "eeRuleEditorTableHeaderLine", class: "eeRuleEditorTableHeaderLine" });
table.append(header);
header.append($("<th />", { class: "eeRuleEditorTableCheckboxColumn" }));
header.append($("<th />", { class: "eeRuleEditorTableNameColumn", width: "5%" }).append(txt("lblName")));
header.append($("<th />", { class: "eeRuleEditorTableMatchColumn", width: "40%" }).append(txt("lblMatch")));
header.append($("<th />", { class: "eeRuleEditorTableSkipColumn", width: "30%" }).append(txt("lblSkip")));
header.append($("<th />", { class: "eeRuleEditorTableReplaceColumn", width: "5%" }).append("<i>" + txt("lblReplace") + "</i>"));
header.append($("<th />", { class: "eeRuleEditorTableTestColumn", width: "10%" }).append("<i>" + txt("lblTest") + "</i>"));
header.append($("<th />", { class: "eeRuleEditorTableNotesColumn", width: "10%" }).append("<i>" + txt("lblNotes") + "</i>"));
header.append($("<th />", { class: "eeRuleEditorTableCopyColumn" }));
addSection("eeRulesPane", "eeRulesPaneContent", txt("lblRules"), table, true);
for (var i = 0; i < rules.length; i++) {
addRuleEditor(i);
}
// Options
addSection("eeOptionsPane", "eeOptionsPaneContent", txt("lblOptions"), null, true);
$("#eeOptionsPaneContent").append($("<div/>").append($("<input />", { type: "checkbox", id: "eeOptionCB_useSkiplist", checked: (useSkiplist[SCANNER]) })).append($("<label />", { for: "eeOptionCB_useSkiplist" }).append(txt("lblUseSkiplist"))));
$("#eeOptionsPaneContent").append($("<div/>").append($("<input />", { type: "number", id: "eeOptionCB_chunkSize", value: chunkSize, min: 0 })).append($("<label />", { for: "eeOptionCB_chunkSize" }).append(txt("lblChunkSize"))));
$("#eeOptionsPaneContent").append($("<div/>").append($("<input />", { type: "checkbox", id: "eeOptionCB_listAll", checked: (listAll) })).append($("<label />", { for: "eeOptionCB_listAll" }).append(txt("lblListAll"))));
// Namespaces
addSection("eeNamespacePane", "eeNamespacePaneContent", txt("lblNamespaces"), null, true);
$("#eeNamespacePaneContent").css("column-width", "200px");
for (var id in mw.config.get("wgFormattedNamespaces")) {
var name = (mw.config.get("wgFormattedNamespaces")[id] === "") ? txt("
$("#eeNamespacePaneContent").append($("<div/>").append($("<input />", { type: "checkbox", id: "eeNamespaceCB_" + id, checked: ($.inArray(Number(id), namespaces[SCANNER]) != -1) })).append($("<label />", { for: "eeNamespaceCB_" + id }).append(name)));
}
Zeile 261 ⟶ 410:
$("#eeSearchPaneContent").append($("<div />").append($("<input />", { type: "file", id: "eeFile", name: "eeFile" }), false));
$("#eeSearchPaneContent").append($("<br/>"));
$("#eeSearchPaneContent").append($("<div />").append($("<input />", { type: "button", id: "eeSearch", name: "eeSearch"
// Output section
$("#eeSearchPaneContent").append($("<div/>", { id: "eeStatus" }));
$("#eeSearchPaneContent").append($("<div/>", { id: "eeProgress" }));
$("#eeSearchPaneContent").append($("<br/>"));
$("#eeSearchPaneContent").append($("<output/>", { id: "eeResults" }));
// Assure collapsible sections are made collapsible
mw.loader.using("mediawiki.page.ready", function () {
//if ($("#eeInstallation").length) {
//}
$(".mw-collapsible").makeCollapsible();
});
// Button: "Search"/"Abort"
$("#eeSearch").click(function() {
setStatus(txt("statAborted"));
} else {
alert("a");
applySettingsFromUI();
}
});
setRunning(false);
}
// Perform dump scan
function scanFile() {
var reader = new FileReader();
var file = document.getElementById("eeFile").files[0];
start = 0;
stop = start + chunkSize;
$("#eeResults").
var header = $("<tr />", { id: "eeResultTableHeaderLine", class: "eeResultTableHeaderLine" });
$("#eeResultTable").append(header);
header.append($("<th />", { class: "eeResultTableTitleColumn" }).append(txt("lblTitle")));
header.append($("<th />", { class: "eeResultTableRuleColumn" }).append(txt("lblRule")));
header.append($("<th />", { class: "eeResultTableMatchColumn" }).append(txt("lblMatch")));
setStatus(txt("statCheckingRules"));
setProgress("");
results = 0;
startTime = new Date();
if (! checkRules()) {
return;
}
setStatus(txt("
reader.onloadend = function(e) {
if (
return;
}
var percentage = (Math.min(stop, file.size) / file.size) * 100;
setProgress(percentage.toFixed(0) + "% (" + Math.min(stop, file.size) + " of " + file.size + " bytes)");
// Trim chopped-of tags
var text = e.target.result;
Zeile 345 ⟶ 486:
text = "<mediawiki>" + nextText + text;
}
var lastCloseText = text.lastIndexOf("</page>");
if (lastCloseText < 0) {
setStatus(txt("
return;
}
nextText = text.substring(lastCloseText + "</page>".length);
text = text.substring(0, lastCloseText + "</page>".length) + "</mediawiki>";;
// Detect base
if (start === 0) {
Zeile 362 ⟶ 503:
base = text.substring(baseStart + "<base>".length, text.indexOf("</base>"));
base = base.substring(0, base.lastIndexOf("/") + 1);
if (baseStart < 0 || base.length === 0) {
setStatus(txt("
return;
}
setStatus(txt("
}
// Search
$(text).find("page").each(function() {
// Check namespace
if ($.inArray(Number($(this).find("ns").text()), namespaces[SCANNER]) == -1) {
return;
}
// Check redirect status
if (ignoreRedirects && $(this).find("redirect").length > 0) {
return;
}
});
// Next chunk
if (stop < file.size) {
start = start + chunkSize;
stop = stop + chunkSize;
var blob = file.slice(start, stop);
reader.readAsText(blob);
Zeile 397 ⟶ 538:
var sec = ((Math.floor(msec / 1000) % 60 < 10) ? "0" : "") + Math.floor(msec / 1000) % 60;
var min = ((Math.floor(msec / 1000 / 60) < 10) ? "0" : "") + Math.floor(msec / 1000 / 60);
setStatus(txt("
}
};
if (file == null || ! file) {
setStatus(txt("
return;
}
var blob = file.slice(start, stop + 1);
reader.readAsText(blob);
}
// Startup
$(document).ready(function() {
if (! window.File || ! window.FileReader || ! window.Blob) {
setStatus(txt("
return;
}
if (
mw.util.addPortletLink("p-navigation", mw.util.wikiGetlink(scannerPage), txt("
}
if (typeof rules === "undefined" || rules == null || rules.length == 0) {
setStatus(txt("
return;
}
if (activated[SCANNER] && mw.config.get("wgPageName") == scannerPage && mw.config.get("wgAction") === "view"
// Scanner view
mw.util.addCSS("div.eeSection { border: 1px solid black; padding: 8px; }");
mw.util.addCSS(".eeResultTable td { border-top: 1px solid #CCCCCC; padding: 4px }");
loadScannerUI();
} else if (activated[MARKER] && $.inArray(mw.config.get("wgNamespaceNumber"), namespaces[MARKER]) != -1 && mw.config.get("wgAction") === "view") {
// Article view: Marker
mw.util.addCSS("span.eeMarker { " + markerStyle + " }");
}
});
|