Benutzer:Schnark/js/antispoof.js
Erscheinungsbild
< Benutzer:Schnark | js
Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.
- Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
- Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
- Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
//Dokumentation unter [[Benutzer:Schnark/js/antispoof]] <nowiki>
/*global mediaWiki: false */
(function($, mw, libs){
function tooltipGenC (map, def) {
return function (x) {
for (var c in map) {
if (x.indexOf(c) !== -1) {
return map[c];
}
}
return def;
};
}
function tooltipGenR (map, def) {
return function (x) {
var r, c = x.charAt(0);
for (r in map) {
if (map[r].test(c)) {
return r;
}
}
return def;
};
}
function v2 () {
var gcCf = '\u0600-\u0603\u06DD\u070F\u17B4\u17B5\u200B\u200F\u202A-\u202E\u2060-\u2064\u206A-\u206F\uFEFF\uFFF9-\uFFFB', //gc = Cf ohne U+200E (LRM), U+00AD (SHY), U+200D (ZWJ), U+200C (ZWNJ) und ohne Zeichen außerhalb Plane 0
//gcCn TODO
gcCc = '\u0000-\u0008\u000B\u000C-\u001F\u007F-\u009F', //gc = Cc ohne U+0009 (TAB), U+000A (LF)
gcPd = '\u058A\u05BE\u1400\u1806\u2010-\u2012\u2015\u2E17\u2E1A\u301C\u3030\u30A0\uFE31\uFE32\uFE58\uFE63\uFF0D\u2043\u2500', //gc = Pd ohne U+002D (HYPHEN-MINUS), U+2013 (EN), U+2014 (EM), dazu U+2043 (HYPHEN BULLET), U+2500 (BOX DRAWINGS LIGHT HORIZONTAL)
gcZ = '\u1680\u180E\u2000-\u2008\u200A\u2028\u2029\u202F\u205F\u3000', //gc = Z ohne U+0020 (SPACE), U+00A0 (NBSP), U+2009 (THIN SPACE)
gcM = '\u0300-\u034E\u0350-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F', //gc = M ohne U+034F (CGJ), unvollständig, zusätzlich einige nicht zugewiesene Zeichen in entsprechenden Blöcken
gcCo = '\uE000-\uF8FF', //gc = Co ohne Zeichen außerhalb Plane 0
gcSkLm = '\u0060\u005E\u00A8\u00AF\u00B4\u00B8\u02B0-\u02FF', //gc = Sk und gc = Lm, unvollständig, ^ _nicht_ an erster Stelle!
gcCs = '\uD800-\uDFFF',
scLatin = '\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u024F\u1E00-\u1EFF\u2132\u214E\u2C60-\u2C7F\uA722-\uA7FF', //sc = Latin ohne \u00AA\u00BA (ªº), \u0250-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u2071\u207F\u2090-\u209C (Lautschrift), \u2160-\u2188 (römsiche Zahlen) \u212A-\u212B\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A (Kompatibilitätszeichen), inklusive Lücken im Block Lateinisch-D
scGreek = '\u0386-\u03A8\u03AA-\u03BB\u03BD-\u03CE\u1F00-\u1FFF', //sc = Greek (ungefähr), ohne my, Omega
scCyrillic = '\u0400-\u052F\u2DE0-\u2DFF\uA640-\uA69F', //sc = Cyrillic (ungefähr)
scAsian = '\u2E80-\uA4CF', //asiatische Schriften in Plane 0 (ungefähr)
scRTL = '\u0590-\u08FF', //rechts-nach-links-Schriften in Plane 0 (ungefähr)
scLigatur = '\u0600-\u07FF\u0900-\u109F', //Schriften, die ZWJ/ZWNJ verwenden (ungefähr)
scOther = '\u03D0-\u03FF\u0530-\u1CFF\u2C00-\u2C5F\u2C80-\u2DDF\uA4D0-\uA63F\uA6A0-\uA6FF\uA800-\uABFF', //Schriften außer scLatin, scGreek, scCyrillic, scAsian (ungefähr)
compat = '\uF900-\uFEFC\uFF61-\uFFEE', //Kompatibilitätszeichen (inklusive halbbreiten Zeichen)
unerwuenscht = '\u2155-\u218F\u2625-\u2629\u2670\u2671\u2716\u2719-\u271F\u2753-\u2763\u2768-\u2775\u2794-\u27BF\uFFFC\uFFFD', //Brüche, Römische Zahlen, Dingbats, Ersatzzeichen
eawF = '\uFF01-\uFF60\uFFE0-\uFFE6', //eaw = F ohne U+3000 (IDEOGRAHIC SPACE)
charEN = '\u2013',
charEM = '\u2014',
charMINUS = '\u2212',
charNBSP = '\u00A0',
charTHINSPACE = '\u2009',
charLRM = '\u200E',
charSHY = '\u00AD',
charZWJ = '\u200D',
charZWNJ = '\u200C',
charCGJ = '\u034F',
charMy = '\u03BC',
charOmega = '\u03A9',
reControl = '.?[' + gcCf + gcCc + charCGJ + (mw.config.get('wgNamespaceNumber') === 0 ? charSHY : '') + '].?', //im Quelltext .?[gcCf gcCc charCGJ charSHY charLRM].?
reLRM = '(?:^|[^' + scRTL + '])' + charLRM + '(?:[^' + scRTL + ']|$)',
reZWJZWNJ = '(?:^|[^' + scLigatur + '])[' + charZWJ + charZWNJ+ '](?:[^' + scLigatur + ']|$)',
reDash = '[' + gcPd + ']',
reEM1 = '\\S\\s*' + charEM,
reEM2 = charEM + '\\s*\\S',
reSpace = '.?[' + gcZ + '].?', //im Quelltext .?[gcZ charNBSP charTHINSPACE].?
//reUnassigned = '[' + gcCn + ']', TODO
rePrivat = '[' + gcCo + ']',
reNotPlane0 = '[' + gcCs + ']+',
reNoNoNo = '[' + gcSkLm + compat + unerwuenscht + ']',
reFullwidth = '[^' + scAsian + '][' + eawF + '][^' + scAsian + ']',
reLatin1 = '[' + scLatin + '][' + scGreek + charMy + scCyrillic + scOther + ']',
reLatin2 = '[' + scGreek + charOmega + scCyrillic + scOther + '][' + scLatin + ']',
reGreekCyrillic = '[' + scGreek + '][' + scCyrillic + ']|[' + scCyrillic + '][' + scGreek + ']',
reSteuerzeichen = new RegExp('()(' + reControl + (mw.config.get('wgNamespaceNumber') !== -1 ? '|' + reLRM : '') + '|' + reZWJZWNJ + ')', 'g'),
reStriche = new RegExp('()(' + reDash + (mw.config.get('wgNamespaceNumber') === 0 ? '|' + reEM1 + '|' + reEM2 : '') + ')', 'g'),
reLeerzeichen = new RegExp('()(' + reSpace + ')', 'g'),
reUnerwuenscht = new RegExp('()(' + rePrivat + '|' + reNotPlane0 + '|' + reNoNoNo + '|' + reFullwidth + ')', 'g'),
reLateinisch = new RegExp('()(' + reLatin1 + '|' + reLatin2 + ')', 'g'),
reGriechischKyrillisch = new RegExp('()(' + reGreekCyrillic + ')', 'g'),
reBennenen = new RegExp('()([' + charTHINSPACE + charEN + charMINUS + (mw.config.get('wgNamespaceNumber') === 0 ? charNBSP : '') + ']' + (mw.config.get('wgNamespaceNumber') !== 0 ? '|.?' + charSHY + '.?' : '') + ')', 'g'),
//reVielleichtBenennen = new RegExp('()(.?[' + gcM + ']+|(?:^|[' + scRTL + '])' + charLRM + '.?|.?' + charLRM + '(?:[' + scRTL + '|$)|(?:^|[' + scLigatur + '])[' + charZWJ + charZWNJ + '].?|.?[' + charZWJ + charZWNJ + '](?:[' + scLigatur + '|$))', 'g'),
tooltipSteuerzeichen = tooltipGenC({
'\u00AD': 'An dieser Stelle steht ein weiches Trennzeichen (SHY)!',
'\u200E': 'An dieser Stelle steht ein Links-nach-rechts-Zeichen (LRM)!',
'\u200F': 'An dieser Stelle steht ein Rechts-nach-links-Zeichen (RLM)!',
'\u200C': 'An dieser Stelle steht ein nullbreiter Nichtverbinder (ZWNJ)!',
'\u200D': 'An dieser Stelle steht ein nullbreiter Verbinder (ZWJ)!',
'\u200B': 'An dieser Stelle steht ein nullbreites Leerzeichen!',
'\u034F': 'An dieser Stelle steht ein kombinierender Graphemverbinder (CGJ)!'
}, 'An dieser Stelle steht ein unsichtbares Steuerzeichen!'),
tooltipStriche = tooltipGenC({
'\u2010': 'Dies ist ein Unicode-Bindestrich!',
'\u2011': 'Dies ist ein nicht-umbrechender Bindestrich!',
'\u2012': 'Dies ist ein ziffernbreiter Bindestrich!',
'\u2014': 'Dies ist ein Geviertstrich!',
'\u2015': 'Dies ist ein horizontaler Strich!',
'\u2043': 'Dies ist ein Aufzählungsstrich!'
}, 'Dieser Strich sollte nicht verwendet werden!'),
tooltipLeerzeichen = tooltipGenC({
'\u3000': 'An dieser Stelle steht ein ideografisches Leerzeichen!'
}, 'An dieser Stelle steht ein ungewöhnliches Leerzeichen!'),
tooltipUnerwuenscht = tooltipGenR({
'Dieses Zeichen gehört Unicode-Block "Privater Gebrauch" und hat daher in einem Text normalerweise nichts verloren!': new RegExp(rePrivat),
'Dieses Zeichen liegt nicht in der Ebene 0 und wird daher nicht überall korrekt angezeigt. Wenn es sich vermeiden lässt, sollte es nicht verwendet werden!': new RegExp(reNotPlane0)
}, 'Dieses Zeichen ist nicht erwünscht!'),
tooltipLateinisch = 'Hier stößt ein lateinischer Buchstabe mit einem Zeichen aus einer anderen Schrift zusammen!',
tooltipGriechischKyrillisch = 'Hier stößt ein griechischer oder kyrillischer Buchstabe mit einem Zeichen aus einer anderen Schrift zusammen!',
tooltipBennenen = tooltipGenC({
'\u2013': 'Gedanken-/Bis-/etc. -strich',
'\u00A0': 'NBSP',
'\u2212': 'Minus',
'\u2009': 'schmales Leerzeichen',
'\u00AD': 'weiches Trennzeichen'
}),
rot = '#FF8080',
grau = '#C0C0C0',
count = 0,
todo = [
//regexp, hint, color, count
[reSteuerzeichen, tooltipSteuerzeichen, rot, true],
[reStriche, tooltipStriche, rot, true],
[reLeerzeichen, tooltipLeerzeichen, rot, true],
[reUnerwuenscht, tooltipUnerwuenscht, rot, true],
[reLateinisch, tooltipLateinisch, rot, true],
[reGriechischKyrillisch, tooltipGriechischKyrillisch, rot, true],
[reBennenen, tooltipBennenen, grau, false]
];
$(function () {
$.eachAsync(todo, {
end: function () {
if (count > 0) {
$('#firstHeading').after('<span class="antispoof-count noprint">' + count + ' verdächtige Stelle' + (count === 1 ? '' : 'n') + ' gefunden!</span>');
}
},
loop: function (i, data) {
var c = libs.highlight.highlight(data[0], data[1], data[2], 'antispoof-mark');
if (data[3]) {
count += c;
}
}
});
});
}
/*
var antispoof = {
version: 1.4,
rot: '#FF8080',
grau: '#C0C0C0',
ugly: false, //hässliches Zeug um Rest der Seite abzudunklen?
count: 0, //Anzahl der verdächtigen Stellen
unsichtbar: '\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F\u00AD\u2000-\u2008\u200A-\u200D\u200F\u2028-\u202F\u205F-\u206F\u3000', //unsichtbare Zeichen außer TAB (kommt in Versionsunterschieden vor), LF, CR, SPACE, NBSP, THINSPACE, LRM (nur für Spezialseiten)
punkt: '\u0009\u000A\u000D\u0020-\u0040\u005B-\u0060\u007B-\u007E\u00A0-\u00AC\u00AE-\u00BF\u00D7\u00F7\u02B0-\u02FF\u2009\u2010-\u2027\u2030-\u205E\u2070\u2074-\u2079\u2080-\u2089\u2122\u2190-\u22FF', //Satz- und Leerzeichen, Zahlen, Abstandsbestimmung u. ä.
latein: '\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02AF\u1E00-\u1EFF\u2C60-\u2C7F\uA720-\uA7FF', //lateinische Buchstaben (ink. IPA)
griechisch: '\u0370-\u03FF\u1F00-\u1FFF', //griechische Buchstaben
kyrillisch: '\u0400-\u052F', //kyrillische Buchstaben
cjk: '\u2E80-\u2EFF\u3001-\u303F\u31C0-\u31EF\u3200-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF',
sonstiges: '\u0530-\u1DBF\u2071-\u2073\u207A-\u207F\u208A-\u20CF\u2100-\u2121\u2123-\u218F\u2300-\u24FF\u2C00-\u2C5F\u2C80-\u2E7F\u2F00-\u2FFF\u3040-\u31BF\u31F0-\u31FF\u4DC0-\u4DFF\uA000-\uA71F\uA800-\uD7FF\uFB00-\uFE1F\uFE30-\uFFEF', //Buchstaben aus anderen Alphabeten und sonstige Zeichen
kombinierend: '\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F', //kombinierende Zeichen
privat: '\uE000-\uF8FF', //privater Gebrauch
unerwuenscht: '\u0060\u00B4\u2010\u2011\u2012\u2015\u2043\u2155-\u218F\u2625-\u2629\u2670\u2671\u2716\u2719-\u271F\u2753-\u2763\u2768-\u2775\u2794-\u27BF\uFE50-\uFE6F\uFF00-\uFFFD', //aus irgendwelchen Gründen nicht erwünscht, aber oben nicht erfasst (komische Striche (Geviertstrich nur in NS 0), Darstellungsvarianten, Dingbats, etc.)
benennen: '\u0250-\u02AF\u2009\u2013\u2212\u2500', //nur mit Tooltip benennen (im ANR NBSP zusätzlich)
rtl: '\u0590-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF',
zwj_ok: '\u0590-\u109F',
regexp_unsichtbar: null, // /()((?:^|.)[unsichtbar](?:.|$))/g
regexp_privat: null, // /()([privat]+)/g
regexp_kombinierend: null, // /()([kombinierend].)/g
regexp_latein: null, // /([^latein punkt unsichtbar kombinierend])([latein]+)/g
regexp_griechisch: null, // /([^griechisch punkt unsichtbar kombinierend])([griechisch]+)/g
regexp_kyrillisch: null, // /([^kyrillisch punkt unsichtbar kombinierend])([kyrillisch]+)/g
regexp_sonstiges: null, // /([^sonstiges cjk punkt unsichtbar kombinierend])([sonstiges cjk]+)/g
regexp_unerwuenscht: null, // /()([unerwuenscht])/g
regexp_benennen: null, // /()([benennen])/g
regexp_rtl1: null, // /(^|[^rtl])RLM([rtl]|$)/
regexp_rtl2: null, // /(^|[rtl])LRM([^rtl]|$)/
regexp_zwj_ok: null, // /[zwj_ok][\u200C\u200D][zwj_ok]/
regexp_cjk: null, // /[cjk]IDSPACE[cjk]/
init: function() {
if (mw.config.get('wgNamespaceNumber') != -1) {
antispoof.unsichtbar += '\u200E';
}
if (mw.config.get('wgNamespaceNumber') === 0) {
antispoof.benennen += '\u00A0';
antispoof.unerwuenscht += '\u2014';
}
antispoof.regexp_unsichtbar = new RegExp ('()((?:^|.)[' + antispoof.unsichtbar + '](?:.|$))', 'g');
antispoof.regexp_privat = new RegExp ('()([' + antispoof.privat + ']+)', 'g');
antispoof.regexp_kombinierend = new RegExp ('()(.[' + antispoof.kombinierend + '])', 'g');
antispoof.regexp_latein = new RegExp ('([^' + antispoof.latein + antispoof.punkt + antispoof.unsichtbar + antispoof.kombinierend + '])([' +
antispoof.latein + ']+)', 'g');
antispoof.regexp_griechisch = new RegExp ('([^' + antispoof.griechisch + antispoof.punkt + antispoof.unsichtbar + antispoof.kombinierend + '])([' +
antispoof.griechisch + ']+)', 'g');
antispoof.regexp_kyrillisch = new RegExp ('([^' + antispoof.kyrillisch + antispoof.punkt + antispoof.unsichtbar + antispoof.kombinierend + '])([' +
antispoof.kyrillisch + ']+)', 'g');
antispoof.regexp_sonstiges = new RegExp ('([^' + antispoof.sonstiges + antispoof.cjk + antispoof.punkt + antispoof.unsichtbar + antispoof.kombinierend + '])([' +
antispoof.sonstiges + antispoof.cjk + ']+)', 'g');
antispoof.regexp_unerwuenscht = new RegExp ('()([' + antispoof.unerwuenscht + '])', 'g');
antispoof.regexp_benennen = new RegExp ('()([' + antispoof.benennen + '])', 'g');
antispoof.regexp_rtl1 = new RegExp ('(^|[^' + antispoof.rtl + '])\u200F([' + antispoof.rtl + ']|$)');
antispoof.regexp_rtl2 = new RegExp ('(^|[' + antispoof.rtl + '])\u200E([^' + antispoof.rtl + ']|$)');
antispoof.regexp_zwj_ok = new RegExp ('[' + antispoof.zwj_ok + '][\u200C\u200D][' + antispoof.zwj_ok + ']');
antispoof.regexp_cjk = new RegExp ('[' + antispoof.cjk + ']\u3000[' + antispoof.cjk + ']');
$(antispoof.mark);
},
mark: function() {
antispoof.count = 0;
var todo = [
//regexp, hint, color, count
[antispoof.regexp_unsichtbar,
function (x) {
if (x.indexOf('\u00AD') != -1) return 'An dieser Stelle steht ein weiches Trennzeichen!';
if (x.indexOf('\u200B') != -1) return 'An dieser Stelle steht ein nullbreites Leerzeichen!';
if (x.indexOf('\u200C') != -1) return 'An dieser Stelle steht ein nullbreiter Nichtverbinder!';
if (x.indexOf('\u200D') != -1) return 'An dieser Stelle steht ein nullbreiter Verbinder!';
if (x.indexOf('\u200E') != -1) return 'An dieser Stelle steht ein Links-nach-rechts-Zeichen!';
if (x.indexOf('\u200F') != -1) return 'An dieser Stelle steht ein Rechts-nach-links-Zeichen!';
if (x.indexOf('\u3000') != -1) return 'An dieser Stelle steht ein ideografisches Leerzeichen!';
return 'Dieses unsichtbare Zeichen ist kein normales Leerzeichen!';},
function (x) {
if (x.match(antispoof.regexp_rtl1)) return antispoof.grau;
if (x.match(antispoof.regexp_rtl2)) return antispoof.grau;
if (x.match(antispoof.regexp_zwj_ok)) return antispoof.grau;
if (x.match(antispoof.regexp_cjk)) return antispoof.grau;
return antispoof.rot;},
true],
[antispoof.regexp_privat,
'Dieses Zeichen gehört Unicode-Block "Privater Gebrauch" und hat daher in einem Text normalerweise nichts verloren!',
antispoof.rot,
true],
[antispoof.regexp_unerwuenscht,
function (x) {
if (x.indexOf('\u2010') != -1) return 'Dies ist ein Unicode-Bindestrich!';
if (x.indexOf('\u2011') != -1) return 'Dies ist ein nicht-umbrechender Bindestrich!';
if (x.indexOf('\u2012') != -1) return 'Dies ist ein ziffernbreiter Bindestrich!';
if (x.indexOf('\u2014') != -1) return 'Dies ist ein Geviertstrich!';
if (x.indexOf('\u2015') != -1) return 'Dies ist ein horizontaler Strich!';
if (x.indexOf('\u2043') != -1) return 'Dies ist ein Aufzählungsstrich!';
return 'Dieses Zeichen ist normalerweise in Texten nicht erwünscht!';},
antispoof.rot,
true],
[antispoof.regexp_kombinierend,
'Dieses Zeichen ist aus zwei Zeichen zusammengesetzt, einem Akzent und einem Buchstaben!',
antispoof.grau,
false],
[antispoof.regexp_griechisch,
'Dieses Zeichen ist ein griechischer Buchstabe, anders als das vorhergehende!',
antispoof.rot,
true],
[antispoof.regexp_kyrillisch,
'Dieses Zeichen ist ein kyrillischer Buchstabe, anders als das vorhergehende!',
antispoof.rot,
true],
[antispoof.regexp_sonstiges,
'Dieses Zeichen ist ein Buchstabe aus einem sonstigen Alphabet, anders als das vorhergehende!',
antispoof.rot,
true],
[antispoof.regexp_latein,
'Dieses Zeichen ist ein lateinischer Buchstabe, anders als das vorhergehende!',
antispoof.rot,
true],
[antispoof.regexp_benennen,
function (x) {
if (x == '\u00A0') return 'nbsp';
if (x == '\u2009') return 'thinspace';
if (x == '\u2013') return 'Gedanken-/Bis-/etc. -strich';
if (x == '\u2212') return 'Minus';
if (x == '\u2500') return 'horizontale Linie';
if (x.search(/[\u0250-\u02AF]/) > -1) return 'IPA-Zeichen';
return '\\u' + x.charCodeAt(0).toString(16);},
antispoof.grau,
false]];
var done = function() {
if (antispoof.count > 0) {
$('#firstHeading').after('<span class="antispoof-count noprint">' + antispoof.count + ' verdächtige Stelle' + (antispoof.count == 1 ? '' : 'n') + ' gefunden!</span>');
if (antispoof.ugly) {
mw.util.addCSS('.antispoof-mark {z-index: 20; position: relative;}');
$(document.body).append('<div id="antispoof-overlay" style="position:absolute; top:0; left:0; z-index:10; width:100%; height:100%; background-color:#000; filter:alpha(opacity=60); opacity:0.60;"></div>');
$('#antispoof-overlay').hide();
$('.antispoof-count, #antispoof-overlay').click(function(){$('#antispoof-overlay').css('height', $(document).height()).toggle();});
}
}};
$.eachAsync(todo, {end: done, loop: function(i, data) {
var c = libs.highlight.highlight(data[0], data[1], data[2], 'antispoof-mark');
if (data[3]) antispoof.count += c;
}});
}
};
if (mw.config.get('debug')) window.antispoof = antispoof;
$(document).trigger('loadWikiScript', ['Benutzer:Schnark/js/antispoof.js', antispoof]);
mw.loader.using('jquery.async', antispoof.init);
*/
mw.loader.using('jquery.async', v2);
})(jQuery, mediaWiki, mediaWiki.libs);
//</nowiki>