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
- Internet Explorer/Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
- Opera: Strg+F5
/** AUTOCOMPLETE for CORRECT SECTION in Edit-Summary
*** aut. section summary / (automatische Abschnittserkennung für die Zusammenfassung) ***
* @description [[w:de:Benutzer:Perhelion/sectionSummary]]
* @created 2012-01-07
* @author [[User:Perhelion]], 2012–2017
* @revision 15:17, 15. Aug. 2018 (CEST)
* @license Dual-licensed under the terms of the GFDL v1.2 or the GPL v2.
* @ToDo FIXME: Remove tags from headline!? Inlude existing code?
* @required modules: jquery, mediawiki.util, user.options
**/
/* global jQuery, mediaWiki */
(function ($, mw) {
'use strict';
var libs = mw.libs;
if (libs.autoSectiontId instanceof Object)
return;
libs.autoSectiontId = {
version: '0.55t',
exec: function () {
var $editform = $('#editform'),
name = 'autoSectiontId';
if ($.inArray(mw.config.get('wgAction'), ['edit', 'submit']) < 0 || !$editform.length)
return; // only if editing // || !mw.config.get('wgCurRevisionId')
var sumM = { // default lang en.
'new': 'new section ',
'rem': 'removed section – ',
'top': 'top', // phab:T20004; same name from Gadget-edittop.js
'cancel': name + ' canceled: more than one section was changed'
};
// Local translations
if (mw.config.get('wgContentLanguage') === 'de')
sumM = {
'new': 'Neuer Abschnitt ',
'rem': 'Entfernter Abschnitt – ',
'top': 'Einleitung', // same name from Gadget-Einleitung-bearbeiten.js
'cancel': name + ' Abbruch: mehr als ein Abschnitt wurde verändert'
};
var $textbox = $editform.find('#wpTextbox1'),
txtOld = $.trim($textbox.val()), // original text container
lrL = txtOld.lastIndexOf('\n'),
lnL, // last line (new & old)
$sum = $editform.find('#wpSummary'),
headline = /^=+.+=+.*$/gm,
trimHeadline = /^=+(.+[^=])=+\s*$/m; // headline text only
// console.log("Last old line: ", txtOld.slice(lrL)); // The last line
txtOld = txtOld.slice(0, lrL) + txtOld.slice(lrL).replace(/\n[:*# ]*$/, ''); // Trimmed last line indent, could be changed by another script.
function forceSummary() {
var newS = (/§ion=new/.test(location.search) || $editform.children('input[name|=\'wpSection\']').val() === 'new') ? 1 : 0; // new section
// console.log(newS,$sum.val())
if (newS && $sum.val())
return; // on new section, if there is already a summary, because there is no comment supported
/** Get difference from arrays, equvialent to jQuery .not()
* @return {string}
*/
function _not(s, s2) {
return $.grep(s, function (x) {
/* for (var i = 0; i < s2.length; i++) {
// lesser exact
if (s2[i].indexOf(x) !== -1) {
s2.splice(i, 1);
return false;
}
}
return true;*/
return $.inArray(x, s2) < 0; // too exact
})[0]; // Only first?
}
var txt = $.trim($textbox.val()),
remS, // Boolean section removed
sectNamesOld = txtOld.match(headline) || [], // Array
sectNames = txt.match(headline) || [], // Array
// lastHeadlineOld = trimHeadline.exec(RegExp.lastMatch)[1],
// lastHeadline = trimHeadline.exec(RegExp.lastMatch)[1],
sections_len = sectNames.length + 1,
sections_lenOld = sectNamesOld.length + 1,
section = '',
comp = 0, // compare counter
sumTxt = '',
$wpAS = $editform.find('input[name|=\'wpAutoSummary\']'),
sumOld = /^( *\/\*.+\*\/ *)?(.*) *$/.exec($sum.val())[2];
// console.log("Headlines: ",sectNamesOld, sectNames,"length", sectNamesOld.length, sectNames.length);
// egalize temporary different whitespaces
function _uniSectNames(arr) {
return $.map(arr, function (x) {
return x.replace(/^(==+) *([^\n]+[^ ]) *\1 *$/m, '$1 $2 $1');
});
}
/** Get difference from arrays, equvialent to jQuery .not()
* @para b {boolean} (for compare)
* @return array
*/
function doComp(b) { // made headline compare
var uSectNamesOld = _uniSectNames(sectNamesOld);
var uSectNames = _uniSectNames(sectNames);
if (!comp)
comp = new Array(sections_len);
for (i = 0; i < sections_len; i++) {
comp[i] = comp[i] || 0;
if ($.inArray(uSectNames[i], uSectNamesOld) < 0) {
b = true;
comp[i] = b;
}
}
if (!b)
comp = 0; // reset for fail
return comp;
}
/* check section level, get parent section and made unique */
function uniqueSect(c) {
// console.log("uniqueSect before: ",c,sections_len,sectLvl);
var s = [[0, 8]], // sections change counter [section id, heading level]
hl,
h,
i;
for (i = sections_len - 1; i > 0; i--) { // try c compare unique
hl = sectLvl[i]; // level of current section
h = s[0][1]; // level of last changed section
// console.log(i, c[i], "current & last section hl, h", hl, h, s, sectNames[i]);
if (c[i]) // compare
if (hl < h) { s = [[i, hl]]; } else {
if (hl > h)
sectLvl[i] = h;
s.unshift([i, h]);
}
else if (hl < h && s.length > 1)
s = [[i, hl]]; // unique
}
// console.log("uniqueSect End: ", s,s.length,c,sectNames,s[0][1]);
return (s.length < 2 && s[0][1] !== 8 && !c[0]) ? sectNames[s[0][0]] : s;
}
// console.log('sections_lenOld, sections_len ', sections_lenOld, sectNamesOld, sections_len, sectNames);
if (sections_len + sections_lenOld === 2)
return; // console.log( ' canceled: no subject/headline found ', sections_len, sections_lenOld );
/* Made headlines level */
var sectLvl = [0],
i;
for (i = 1; i < sections_len; i++)
sectLvl[i] = sectNames[i - 1].match(/^=+/m)[0].length;
/** New headline **/
if (sections_lenOld < sections_len) {
if (sections_lenOld + 1 === sections_len) { // only single add
sumTxt = sumM['new']; // the keyword new is reserved
section = _not(_uniSectNames(sectNames), _uniSectNames(sectNamesOld));
} else // try find unique
{ section = uniqueSect(doComp()); }
}
/** Removed headline **/
else if (sections_lenOld > sections_len) {
if (sections_lenOld === sections_len + 1) { // only single remove support
sumTxt = sumM.rem;
section = _not(sectNamesOld, sectNames);
remS = 1;
} else { section = [0, 0]; } // for fail
}
/** Same headline count **/
else if (sections_lenOld === sections_len) {
if ($('#wpMinoredit').is(':checked'))
return; // Minoredit is not supported, because it needs string compare
// check first all section lines, after them also if a headline is changed
/** find the right section **/
var linesOld = txtOld.match(/^.*$/gm), // all lines txt.match(/(.*?\n/g),
lines = txt.match(/^.*$/gm), // with empty lines: txt.match(/(.+/g),
line = 0, // line counter
lineOld = 0,
lines_l = lines.length,
lines_lOld = linesOld.length,
lines_max = Math.max(lines_l, lines_lOld),
sIdOld = 1, // old line numbers
sId = 1, // new -
s,
sectionsOld = [[0, 0]], // +section 0
sections = [[0, 0]]; // +section 0
sectNamesOld.unshift(''); // +section 0
sectNames.unshift(''); // +section 0
i = 0;
comp = doComp(1); // made empty array
// console.log("sectionsOld ", sectNamesOld, sectNamesOld.length, "\nsections ", sectNames, sectNames.length)
// do count lines to sections
for (var l = 0; l < lines_max; l++) { // do sections indexed
// console.log("Do count lines", l, sId, lines[l])
if (sectNames[sId] && sectNames[sId] === lines[l]) {
// console.log(l, sId, "new headline: "+sectNames[sId])
line = l - 1 - line;
sections[sId] = [l];
sections[sId - 1][1] = line;
sId++;
line = l;
}
if (sectNamesOld[sIdOld] && sectNamesOld[sIdOld] === linesOld[l]) {
// console.log(l, sIdOld, "old headline: "+sectNamesOld[sIdOld])
lineOld = l - 1 - lineOld;
sectionsOld[sIdOld] = [l];
sectionsOld[sIdOld - 1][1] = lineOld;
sIdOld++;
lineOld = l;
}
}
// console.log(lines_l,lines_lOld, "last section: ", sectionsOld[sections_lenOld-1], " sections ", sections_lenOld, sectionsOld, sections_len, sections)
// last section length
sections[sections_len - 1][1] = lines_l - sections[sections_len - 1][0] - 1;
sectionsOld[sections_lenOld - 1][1] = lines_lOld - sectionsOld[sections_lenOld - 1][0] - 1;
// sections_len++;
// console.log(" sections old: ",sectionsOld," len ",sections_lenOld, "\n sections new: ",sections," len ",sections_len)
// console.log("All lines_l: "+ lines_l+" lines_lOld: "+lines_lOld)
/** * Line count was _not changed, compare all lines ***/
// if (lines_l === lines_lOld) { // we can't take here a dependency
for (i = 0; i < sections_len; i++) {
// console.log("* check every line * section: ",i, sectionsOld[i][0] + " lines " + sectionsOld[i][1]);
if (sections[i][1] !== sectionsOld[i][1]) { // compare only line quantity (performance reason)
comp[i] = Math.abs(sections[i][1] - sectionsOld[i][1]);
// console.log("* line quantity was changed *", i, comp[i], sections[i]);
continue;
}
for (s = 1; s < sectionsOld[i][1] + 1; s++) {
lineOld = sectionsOld[i][0] + s;
line = sections[i][0] + s;
// console.log(sections[i], " line: ", lineOld , linesOld[lineOld]);
if (linesOld[lineOld].length !== lines[line].length) { // String compare is not yet supported
comp[i]++;
// console.log("section: ",i, sections[i] ," line ≠: ", lineOld, "\nOld: "+linesOld[lineOld]+"\nNew: "+lines[line])
break;
}
}
}
// console.log("comp lines: ", comp)
section = uniqueSect(comp);
// console.log("section len, last comp ", section.length,section, comp[sections_len-1]);
if ($.isArray(section) && section.length > 1 && comp[sections_len - 1] === 1) { // properly only last line changed (tolerance)
lrL = txtOld.slice(txtOld.lastIndexOf('\n'));
lnL = txt.slice(txt.lastIndexOf('\n'));
if (lnL !== lrL) {
// console.log(name + " last line change ignored: ", lrL, lnL);
comp[sections_len - 1] = 0;
section = uniqueSect(comp); // so try again
}
}
}
if (!section)
return; // console.log( name + ' canceled: no modified section found', comp ); //DEBUG
if ($.isArray(section)) // more than one section changed
if (section.length === 1 && comp[0] && section[0][1] === 8) {
section = '=' + sumM.top + '='; // section 0
} else {
// console.warn("FAIL: ", '"' + sumOld + '"', $wpAS.val().indexOf(name), $wpAS.val()); // DEBUG
if ($wpAS.val().indexOf(name) !== -1) // if already ran, remove old forceSummary
$sum.val(sumOld);
// $wpAS.val( $wpAS.val().replace(name,'') );
return console.log(sumM.cancel); // to many changes
}
// console.log("before trimHeadline: ", section);
var sect2 = trimHeadline.exec(section);
if (!sect2 || !sect2[1]) return;
sect2 = $.trim(sect2[1]);
// console.log("after trimHeadline: '%s'", sect2);
/* trim wiki links (to link text) FIXME?: trimLink1 & trimLink2 could be better one regexp? */
var trimLink1 = /\[\[[\s_]*?:?[\s_]*?[^[]*\]\]/.exec(sect2);
var trimLink2 = /[^[\]*?\[\[[\s_]*?:?[\s_]*?([^[|]*|[^]]*\|([^|]]*))\]\]/g.exec(sect2);
// console.log("trimLink: "+ trimLink1 +" , "+ trimLink2);
if (trimLink1 && trimLink2) // if link found trim
sect2 = sect2.replace(trimLink1[0], trimLink2[1]);
// trim external links (to link text) because external wiki links are not provided in the edit summary and can be also to long
sect2 = sect2.replace(/\[https?:\/\/[^\s[\]|]*? +([^\n[\]|]*)?\]/gi, '$1');
if (!sect2)
return;
// throw Error(name + ' failed: section is non compliant!?'); // DEBUG;
if (newS) { // Remove headline from text and put it on the right field
// newS = new RegExp('^=+ *' + section + ' *=+\\s+$','m'); // FIXME section need to convert to regexp
txt = txt.replace(section, '');
// console.log("newS", section, newS, txt);
$sum.val(sect2);
return $textbox.val($.trim(txt)); // save test before
}
sect2 = (remS) ? sumTxt + sect2 : sumTxt + '/* ' + sect2 + ' */';
var wpAS = $wpAS.val().indexOf(name); // save old changes of Sum in wpAutoSummary, if changes remove this
if (wpAS < 0) { $wpAS[0].value += name + sect2; }
// only needed without LIVEPREVIEW
else { // On Preview, Diff remove own old Sum and delete unfortunately actual section
// console.log("sect2, sumOld", sect2, sumOld);
sumOld = sumOld.replace(sect2, '');
if (!mw.user.options.get('uselivepreview') && sect2 !== $wpAS.val().slice(wpAS + name.length))
sect2 = ''; // FIXME: without LIVEPREVIEW / Ajax we can't be SURE
// console.log(sumM.cancel + " and LIVEPREVIEW not activated!"); // to many changes
}
$sum.val(sect2 + ' ' + $.trim(sumOld));
} // event forceSummary // FIXME: old wpTextbox1.value get lost? Works for sure only with LIVEPREVIEW?
$('#wpSave,#wpPreview,#wpDiff').click(forceSummary);
}
};
$(function () {
if (mw.config.get('wgPageContentModel') === 'wikitext')
mw.loader.using('user.options', libs.autoSectiontId.exec);
});
}(jQuery, mediaWiki));