User:MJL/ARA-light.js
Appearance
< User:MJL
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
This user script seems to have a documentation page at User:MJL/ARA-light. |
// <nowiki>
// Everything is encapsulated in a private namespace object---``JJJ'':
var JJJ = JJJ || {};
$(document).ready(function()
{
//initialize Constants
JJJ.Constants = getARAConstants();
//only execute on the edit page
if (!JJJ.Constants.IS_EDIT_PAGE || JJJ.Constants.IS_JS_PAGE || JJJ.Constants.ARTICLE_TEXT_BOX_ELEMENT == null)
return;
//init functions and rules
JJJ.Functions = getARAFunctions();
JJJ.Rules = getARARules();
//init UI
$('#editform').prepend(JJJ.Constants.SUGGESTION_BOX_DIV);
$('#wpSummaryLabel').prepend(JJJ.Constants.ADD_TO_SUMMARY_DIV);
JJJ.Functions.scan(); //init scan now
JJJ.Functions.observeWikiText(JJJ.Constants.delayScan); // ... and every time the user pauses typing
});
function getARAConstants()
{
var ARA_Constants = ARA_Constants || {};
//article text box element
ARA_Constants.ARTICLE_TEXT_BOX_ELEMENT = $("#wpTextbox1");
//are we on an Edit page?
ARA_Constants.IS_EDIT_PAGE = mw.config.get('wgAction') === 'edit' || mw.config.get('wgAction') === 'submit';
//are we on a JS page?
ARA_Constants.IS_JS_PAGE = mw.config.get('wgRelevantPageName').endsWith('.js');
//the ARA Suggestion box, which appears above the editing section
ARA_Constants.SUGGESTION_BOX_DIV = $('<div>', {'id':'suggestionBox.ARA', 'style':'border:dashed #ccc 1px;color:#888;'});
//the Add to Summary box, which appears near the edit summary
ARA_Constants.ADD_TO_SUMMARY_DIV = $('<div>', {'id':'addToSummaryBox.ARA', 'style':'border:dashed #ccc 1px;color:#888;display:none;'});
ARA_Constants.DEFAULT_MAX_SUGGESTIONS = 8;
ARA_Constants.maxSuggestions = ARA_Constants.DEFAULT_MAX_SUGGESTIONS;
ARA_Constants.suggestions; // : Suggestion[]
ARA_Constants.appliedSuggestions = {}; // : Map<String, int>
ARA_Constants.scannedText = null; // remember what we scan, to check if it is
// still the same when we try to fix it
ARA_Constants.BIG_THRESHOLD = 100 * 1024;
ARA_Constants.isBigScanConfirmed = false; // is the warning about a big article confirmed
ARA_Constants.isTalkPageScanConfirmed = false;
ARA_Constants.scanTimeoutId = null; // a timeout is set after a keystroke and before
// a scan, this variable tracks its id
return ARA_Constants;
}
function getARAFunctions()
{
var ARA_Functions = ARA_Functions || {};
// Browsers offer means to highlight text between two given offsets (``start''
// and ``end'') in a textarea, but some of them do not automatically scroll to it.
// This function is an attempt to simulate cross-browser selection and scrolling.
ARA_Functions.setSelectionRange = function (ta, start, end) {
// Initialise static variables used within this function
var _static = arguments.callee; // this is the Function we are in. It will be used as a poor man's function-local static scope.
if (ta.setSelectionRange) {
// Guess the vertical scroll offset by creating a
// separate hidden clone of the original textarea, filling it with the text
// before ``start'' and computing its height.
if (_static.NEWLINES == null) {
_static.NEWLINES = '\n'; // 64 of them should be enough.
for (var i = 0; i < 6; i++) {
_static.NEWLINES += _static.NEWLINES;
}
}
if (_static.helperTextarea == null) {
_static.helperTextarea = document.createElement('TEXTAREA');
_static.helperTextarea.style.display = 'none';
document.body.appendChild(_static.helperTextarea);
}
var hta = _static.helperTextarea;
hta.style.display = '';
hta.style.width = ta.clientWidth + 'px';
hta.style.height = ta.clientHeight + 'px';
hta.value = _static.NEWLINES.substring(0, ta.rows) + ta.value.substring(0, start);
var yOffset = hta.scrollHeight;
hta.style.display = 'none';
ta.focus();
ta.setSelectionRange(start, end);
if (yOffset > ta.clientHeight) {
yOffset -= Math.floor(ta.clientHeight / 2);
ta.scrollTop = yOffset;
// Opera does not support setting the scrollTop property
if (ta.scrollTop != yOffset) {
// todo: Warn the user or apply a workaround
}
} else {
ta.scrollTop = 0;
}
} else {
// IE incorrectly counts '\r\n' as a signle character
start -= ta.value.substring(0, start).split('\r').length - 1;
end -= ta.value.substring(0, end).split('\r').length - 1;
var range = ta.createTextRange();
range.collapse(true);
range.moveStart('character', start);
range.moveEnd('character', end - start);
range.select();
}
};
// getPosition(e), observe(e, x, f), stopObserving(e, x, f),
// and stopEvent(event) are inspired by the prototype.js framework
// http://prototypejs.org/
ARA_Functions.getPosition = function (e) {
var x = 0;
var y = 0;
do {
x += e.offsetLeft || 0;
y += e.offsetTop || 0;
e = e.offsetParent;
} while (e);
return {x: x, y: y};
};
ARA_Functions.observe = function (e, eventName, f) {
if (e.addEventListener) {
e.addEventListener(eventName, f, false);
} else {
e.attachEvent('on' + eventName, f);
}
};
ARA_Functions.stopObserving = function (e, eventName, f) {
if (e.removeEventListener) {
e.removeEventListener(eventName, f, false);
} else {
e.detachEvent('on' + eventName, f);
}
};
ARA_Functions.stopEvent = function (event) {
if (event.preventDefault) {
event.preventDefault();
event.stopPropagation();
} else {
event.returnValue = false;
event.cancelBubble = true;
}
};
// ARA_Functions.anchor() is a shortcut to creating a link as a DOM node:
ARA_Functions.anchor = function (text, href, title) {
var e = document.createElement('A');
e.href = href;
e.appendChild(document.createTextNode(text));
e.title = title || '';
return e;
};
// ARA_Functions.link() produces the HTML for a link to a Wikipedia article as a string.
// It is convenient to embed in a help popup.
ARA_Functions.hlink = function (toWhat, text) {
var wgServer = window.wgServer || 'http://en.wikipedia.org';
var wgArticlePath = window.wgArticlePath || '/wiki/$1';
var url = (wgServer + wgArticlePath).replace('$1', toWhat);
return '<a href="' + url + '" target="_blank">' + (text || toWhat) + '</a>';
};
// === Helpers a la functional programming ===
// A higher-order function---produces a cached version of a one-arg function.
ARA_Functions.makeCached = function (f) {
var cache = {}; // a closure; the cache is private for f
return function (x) {
return (cache[x] != null) ? cache[x] : (cache[x] = f(x));
};
};
// === Editor compatibility layer ===
// Controlling access to wpTextbox1 helps abstract out compatibility
// with editors like wikEd (http://en.wikipedia.org/wiki/User:Cacycle/wikEd)
ARA_Functions.getWikiText = function () {
if (window.wikEdUseWikEd) {
var obj = {sel: WikEdGetSelection()};
WikEdParseDOM(obj, wikEdFrameBody);
return obj.plain;
}
return JJJ.Constants.ARTICLE_TEXT_BOX_ELEMENT.val();
};
ARA_Functions.setWikiText = function (s) {
if (window.wikEdUseWikEd) {
// todo: wikEd compatibility
alert(JJJ.Functions._('Changing text in wikEd is not yet supported.'));
return;
};
JJJ.Constants.ARTICLE_TEXT_BOX_ELEMENT.val(s);
};
ARA_Functions.focusWikiText = function () {
if (window.wikEdUseWikEd) {
wikEdFrameWindow.focus();
return;
}
JJJ.Constants.ARTICLE_TEXT_BOX_ELEMENT.focus();
};
ARA_Functions.selectWikiText = function (start, end) {
if (window.wikEdUseWikEd) {
var obj = x = {sel: WikEdGetSelection(), changed: {}};
WikEdParseDOM(obj, wikEdFrameBody);
var i = 0;
while ((obj.plainStart[i + 1] != null) && (obj.plainStart[i + 1] <= start)) {
i++;
}
var j = i;
while ((obj.plainStart[j + 1] != null) && (obj.plainStart[j + 1] <= end)) {
j++;
}
obj.changed.range = document.createRange();
obj.changed.range.setStart(obj.plainNode[i], start - obj.plainStart[i]);
obj.changed.range.setEnd(obj.plainNode[j], end - obj.plainStart[j]);
WikEdRemoveAllRanges(obj.sel);
obj.sel.addRange(obj.changed.range);
return;
}
ARA_Functions.setSelectionRange(document.getElementById(JJJ.Constants.ARTICLE_TEXT_BOX_ELEMENT.prop('id')), start, end);
};
ARA_Functions.observeWikiText = function (callback) {
// todo: wikEd compatibility
ARA_Functions.observe(document.getElementById(JJJ.Constants.ARTICLE_TEXT_BOX_ELEMENT.prop('id')), 'keyup', JJJ.Functions.delayScan);
};
// === Interaction with the user ===
// ARA_Functions.scan() analyses the text and handles how the proposals are reflected in the UI.
ARA_Functions.scan = function (force)
{
JJJ.Constants.scanTimeoutId = null;
//get article text
var s = JJJ.Functions.getWikiText();
//determine if we actually need to scan
if ((s === JJJ.Constants.scannedText) && !force)
return; // Nothing to do, we've already scanned the very same text
JJJ.Constants.scannedText = s;
//remove all current suggestions
JJJ.Constants.SUGGESTION_BOX_DIV.empty();
// Warn about scanning a big article
if ((s.length > JJJ.Constants.BIG_THRESHOLD) && !JJJ.Constants.isBigScanConfirmed) {
JJJ.Constants.SUGGESTION_BOX_DIV.append(document.createTextNode(
JJJ.Functions._('This article is rather long. ARA may consume a lot of '
+ 'RAM and CPU resources while trying to parse the text. You could limit '
+ 'your edit to a single section, or ')
));
JJJ.Constants.SUGGESTION_BOX_DIV.append(JJJ.Functions.anchor(
JJJ.Functions._('scan the text anyway.'),
'javascript: JJJ.Constants.isBigScanConfirmed = true; JJJ.Functions.scan(true); void(0);',
JJJ.Functions._('Ignore this warning.')
));
return;
}
// Warn about scanning a talk page
if (( mw.config.get('wgCanonicalNamespace') === 'Talk'
|| mw.config.get('wgCanonicalNamespace') === 'User_talk'
|| mw.config.get('wgCanonicalNamespace') === 'Project_talk'
|| mw.config.get('wgCanonicalNamespace') === 'MediaWiki_talk'
)
&& !JJJ.Constants.isTalkPageScanConfirmed
)
{
JJJ.Constants.SUGGESTION_BOX_DIV.append(document.createTextNode(
JJJ.Functions._('ARA is disabled on talk pages, because ' +
'it might suggest changing other users\' comments. That would be ' +
'something against talk page conventions. If you promise to be ' +
'careful, you can ')
));
JJJ.Constants.SUGGESTION_BOX_DIV.append(JJJ.Functions.anchor(
JJJ.Functions._('scan the text anyway.'),
'javascript: JJJ.Constants.isTalkPageScanConfirmed = true; JJJ.Functions.scan(true); void(0);',
JJJ.Functions._('Ignore this warning.')
));
return;
}
//get suggestions
JJJ.Constants.suggestions = JJJ.Functions.getSuggestions(s);
//if there aren't any suggestions, say so
if (JJJ.Constants.suggestions.length === 0)
{
JJJ.Constants.SUGGESTION_BOX_DIV.append(document.createTextNode(
JJJ.Functions._('OK \u2014 ARA found no referencing issues.') // U+2014 is an mdash
));
return;
}
var nSuggestions = Math.min(JJJ.Constants.maxSuggestions, JJJ.Constants.suggestions.length);
JJJ.Constants.SUGGESTION_BOX_DIV.append(document.createTextNode(
(JJJ.Constants.suggestions.length == 1)
? JJJ.Functions._('1 suggestion: ')
: JJJ.Functions._('$1 suggestions: ', JJJ.Constants.suggestions.length)
));
for (var i = 0; i < nSuggestions; i++) {
var suggestion = JJJ.Constants.suggestions[i];
var eA = JJJ.Functions.anchor(
suggestion.name,
'javascript:JJJ.Functions.showSuggestion(' + i + '); void(0);',
suggestion.description
);
suggestion.element = eA;
JJJ.Constants.SUGGESTION_BOX_DIV.append(eA);
if (suggestion.replacement != null)
{
var eSup = document.createElement('SUP');
JJJ.Constants.SUGGESTION_BOX_DIV.append(eSup);
var sup1 = suggestion.sup1 != null ? suggestion.sup1 : 'fix';
eSup.appendChild (
JJJ.Functions.anchor (
JJJ.Functions._(sup1),
'javascript:JJJ.Functions.fixSuggestion(' + i + '); void(0);'
)
);
//sometimes, suggestions may have more than one fix link
if (suggestion.replacement2 != null)
{
var sup2 = suggestion.sup2 != null ? suggestion.sup2 : 'fix2';
eSup.appendChild(document.createTextNode(' | '));
eSup.appendChild(
JJJ.Functions.anchor(
JJJ.Functions._(sup2),
'javascript:JJJ.Functions.fixSuggestion2(' + i + '); void(0);'
)
);
}
if (suggestion.replacement3 != null)
{
var sup3 = suggestion.sup3 != null ? suggestion.sup3 : 'fix3';
eSup.appendChild(document.createTextNode(' | '));
eSup.appendChild(
JJJ.Functions.anchor(
JJJ.Functions._(sup3),
'javascript:JJJ.Functions.fixSuggestion3(' + i + '); void(0);'
)
);
}
}
JJJ.Constants.SUGGESTION_BOX_DIV.append(document.createTextNode(' '));
}
if (JJJ.Constants.suggestions.length > JJJ.Constants.maxSuggestions) {
JJJ.Constants.SUGGESTION_BOX_DIV.append(JJJ.Functions.anchor(
'...', 'javascript: JJJ.Constants.maxSuggestions = 1000; JJJ.Functions.scan(true); void(0);',
JJJ.Functions._('Show All')
));
}
};
// getSuggestions() returns the raw data used by scan().
// It is convenient for unit testing.
ARA_Functions.getSuggestions = function (s) {
var suggestions = [];
var missingRefGroupSuggestions = []; //we want to keep track of the ones we already have so we don't push the same message twice
for (var i = 0; i < JJJ.Rules.length; i++) //for each rule
{
var a = JJJ.Rules[i](s); //execute rule
for (var j = 0; j < a.length; j++) //for each suggestion pushed by the rule
{
var returned_suggestion = a[j];
//if the suggestion is not a missing reference groups suggestion, or it is and we didn't already push this one
if (!returned_suggestion.name.includes("missing reference groups") || !missingRefGroupSuggestions.includes(returned_suggestion.name))
{
suggestions.push(returned_suggestion); //add suggestion to list of suggestions
missingRefGroupSuggestions.push(returned_suggestion.name); //add suggestion to list of suggestions we already have
}
}
}
suggestions.sort(function (x, y) {
return (x.start < y.start) ? -1 :
(x.start > y.start) ? 1 :
(x.end < y.end) ? -1 :
(x.end > y.end) ? 1 : 0;
});
return suggestions;
};
// === Internationalisation ===
// ARA_Functions._() is a gettext-style internationalisation helper
// (http://en.wikipedia.org/wiki/gettext)
// If no translation is found for the parameter, it is returned as is.
// Additionally, subsequent parameters are substituted for $1, $2, and so on.
ARA_Functions._ = function (s) {
if (JJJ.Constants.translation && JJJ.Constants.translation[s]) {
s = JJJ.Constants.translation[s];
}
var index = 1;
while (arguments[index]) {
s = s.replace('$' + index, arguments[index]); // todo: replace all?
index++;
}
return s;
};
// showSuggestion() handles clicks on the suggestions above the edit area
// This does one of two things:
// * on first click---highlight the corresponding text in the textarea
// * on a second click, no later than a fixed number milliseconds after the
// first one---show the help popup
ARA_Functions.showSuggestion = function (k) {
if (JJJ.Functions.getWikiText() != JJJ.Constants.scannedText) {
// The text has changed - just do another scan and don't change selection
JJJ.Functions.scan();
return;
}
var suggestion = JJJ.Constants.suggestions[k];
var now = new Date().getTime();
if ((suggestion.help != null) && (JJJ.Constants.lastShownSuggestionIndex === k) && (now - JJJ.Constants.lastShownSuggestionTime < 1000)) {
// Show help
var p = JJJ.Functions.getPosition(suggestion.element);
var POPUP_WIDTH = 300;
var eDiv = document.createElement('DIV');
eDiv.innerHTML = suggestion.help;
eDiv.style.position = 'absolute';
eDiv.style.left = Math.max(0, Math.min(p.x, document.body.clientWidth - POPUP_WIDTH)) + 'px';
eDiv.style.top = (p.y + suggestion.element.offsetHeight) + 'px';
eDiv.style.border = 'solid ThreeDShadow 1px';
eDiv.style.backgroundColor = 'InfoBackground';
eDiv.style.fontSize = '12px';
eDiv.style.color = 'InfoText';
eDiv.style.width = POPUP_WIDTH + 'px';
eDiv.style.padding = '0.3em';
eDiv.style.zIndex = 10;
document.body.appendChild(eDiv);
JJJ.Functions.observe(document.body, 'click', function (event) {
event = event || window.event;
var target = event.target || event.srcElement;
var e = target;
while (e != null) {
if (e == eDiv) {
return;
}
e = e.parentNode;
}
document.body.removeChild(eDiv);
JJJ.Functions.stopObserving(document.body, 'click', arguments.callee);
});
JJJ.Functions.focusWikiText();
return;
}
JJJ.Constants.lastShownSuggestionIndex = k;
JJJ.Constants.lastShownSuggestionTime = now;
JJJ.Functions.selectWikiText(suggestion.start, suggestion.end);
};
// Usually, there is a ``fix'' link next to each suggestion. It is handled by:
ARA_Functions.fixSuggestion = function(k)
{
var s = JJJ.Functions.getWikiText();
if (s != JJJ.Constants.scannedText) {
JJJ.Functions.scan();
return;
}
var suggestion = JJJ.Constants.suggestions[k];
// the issue is not automatically fixable, return
if (suggestion.replacement == null) {
return;
}
JJJ.Functions.setWikiText(
s.substring(0, suggestion.start)
+ suggestion.replacement
+ s.substring(suggestion.end)
);
JJJ.Functions.selectWikiText(
suggestion.start,
suggestion.start + suggestion.replacement.length
);
// Propose an edit summary unless it's a new section
var editform = document.getElementById('editform');
if (!editform['wpSection'] || (editform['wpSection'].value != 'new')) {
if (JJJ.Constants.appliedSuggestions[suggestion.name] == null) {
JJJ.Constants.appliedSuggestions[suggestion.name] = 1;
} else {
JJJ.Constants.appliedSuggestions[suggestion.name]++;
}
var a = [];
for (var i in JJJ.Constants.appliedSuggestions) {
a.push(i);
}
a.sort(function (x, y) {
return (JJJ.Constants.appliedSuggestions[x] > JJJ.Constants.appliedSuggestions[y]) ? -1 :
(JJJ.Constants.appliedSuggestions[x] < JJJ.Constants.appliedSuggestions[y]) ? 1 :
(x < y) ? -1 : (x > y) ? 1 : 0;
});
var s = '';
for (var i = 0; i < a.length; i++) {
var count = JJJ.Constants.appliedSuggestions[a[i]];
s += ', ' + ((count == 1) ? a[i] : (count + 'x ' + a[i]));
}
// Cut off the leading ``, '' and add ``using ARA''
s = JJJ.Functions._(
'fixed [[Help:CS1 errors#apostrophe markup|CS1 \'\'markup\'\' error(s)]] likely via [[User:MJL/ARA-light|script]]',
s.substring(2)
);
// Render in DOM
JJJ.Constants.ADD_TO_SUMMARY_DIV.empty();
JJJ.Constants.ADD_TO_SUMMARY_DIV.show();
JJJ.Constants.ADD_TO_SUMMARY_DIV.append(JJJ.Functions.anchor(
JJJ.Functions._('Add to summary'),
'javascript:JJJ.Functions.addToSummary(unescape("' + escape(s) + '"));',
JJJ.Functions._('Append the proposed summary to the input field below')
));
JJJ.Constants.ADD_TO_SUMMARY_DIV.append(document.createTextNode(': "' + s + '"'));
}
// Re-scan immediately
JJJ.Functions.scan();
};
// if a suggestion has two 'fix' options, the second option will be handled here
ARA_Functions.fixSuggestion2 = function (k)
{
var s = JJJ.Functions.getWikiText();
if (s != JJJ.Constants.scannedText) {
JJJ.Functions.scan();
return;
}
var suggestion = JJJ.Constants.suggestions[k];
// the issue is not automatically fixable, return
if (suggestion.replacement2 == null) {
return;
}
//otherwise, if we are executing JS, do so
else if (suggestion.replacement2.includes("javascript:"))
{
eval(suggestion.replacement2);
return;
}
JJJ.Functions.setWikiText(
s.substring(0, suggestion.start2)
+ suggestion.replacement2
+ s.substring(suggestion.end2)
);
JJJ.Functions.selectWikiText(
suggestion.start2,
suggestion.start2 + suggestion.replacement2.length
);
// Propose an edit summary unless it's a new section
var editform = document.getElementById('editform');
if (!editform['wpSection'] || (editform['wpSection'].value != 'new')) {
if (JJJ.Constants.appliedSuggestions[suggestion.name] == null) {
JJJ.Constants.appliedSuggestions[suggestion.name] = 1;
} else {
JJJ.Constants.appliedSuggestions[suggestion.name]++;
}
var a = [];
for (var i in JJJ.Constants.appliedSuggestions) {
a.push(i);
}
a.sort(function (x, y) {
return (JJJ.Constants.appliedSuggestions[x] > JJJ.Constants.appliedSuggestions[y]) ? -1 :
(JJJ.Constants.appliedSuggestions[x] < JJJ.Constants.appliedSuggestions[y]) ? 1 :
(x < y) ? -1 : (x > y) ? 1 : 0;
});
var s = '';
for (var i = 0; i < a.length; i++) {
var count = JJJ.Constants.appliedSuggestions[a[i]];
s += ', ' + ((count == 1) ? a[i] : (count + 'x ' + a[i]));
}
// Cut off the leading ``, '' and add ``using ARA''
s = JJJ.Functions._(
'fixed [[Help:CS1 errors#apostrophe markup|CS1 \'\'markup\'\' error(s)]] likely via [[User:MJL/ARA-light|script]]',
s.substring(2)
);
// Render in DOM
JJJ.Constants.ADD_TO_SUMMARY_DIV.empty();
JJJ.Constants.ADD_TO_SUMMARY_DIV.show();
JJJ.Constants.ADD_TO_SUMMARY_DIV.append(JJJ.Functions.anchor(
JJJ.Functions._('Add to summary'),
'javascript:JJJ.Functions.addToSummary(unescape("' + escape(s) + '"));',
JJJ.Functions._('Append the proposed summary to the input field below')
));
JJJ.Constants.ADD_TO_SUMMARY_DIV.append(document.createTextNode(': "' + s + '"'));
}
// Re-scan immediately
JJJ.Functions.scan();
};
ARA_Functions.fixSuggestion3 = function (k)
{
var s = JJJ.Functions.getWikiText();
if (s != JJJ.Constants.scannedText) {
JJJ.Functions.scan();
return;
}
var suggestion = JJJ.Constants.suggestions[k];
if (suggestion.replacement3 == null) { // the issue is not automatically fixable
return;
}
JJJ.Functions.setWikiText(
s.substring(0, suggestion.start3)
+ suggestion.replacement3
+ s.substring(suggestion.end3)
);
JJJ.Functions.selectWikiText(
suggestion.start3,
suggestion.start3 + suggestion.replacement3.length
);
// Propose an edit summary unless it's a new section
var editform = document.getElementById('editform');
if (!editform['wpSection'] || (editform['wpSection'].value != 'new')) {
if (JJJ.Constants.appliedSuggestions[suggestion.name] == null) {
JJJ.Constants.appliedSuggestions[suggestion.name] = 1;
} else {
JJJ.Constants.appliedSuggestions[suggestion.name]++;
}
var a = [];
for (var i in JJJ.Constants.appliedSuggestions) {
a.push(i);
}
a.sort(function (x, y) {
return (JJJ.Constants.appliedSuggestions[x] > JJJ.Constants.appliedSuggestions[y]) ? -1 :
(JJJ.Constants.appliedSuggestions[x] < JJJ.Constants.appliedSuggestions[y]) ? 1 :
(x < y) ? -1 : (x > y) ? 1 : 0;
});
var s = '';
for (var i = 0; i < a.length; i++) {
var count = JJJ.Constants.appliedSuggestions[a[i]];
s += ', ' + ((count == 1) ? a[i] : (count + 'x ' + a[i]));
}
// Cut off the leading ``, '' and add ``using ARA''
s = JJJ.Functions._(
'fixed [[Help:CS1 errors#apostrophe markup|CS1 \'\'markup\'\' error(s)]] likely via [[User:MJL/ARA-light|script]]',
s.substring(2)
);
// Render in DOM
JJJ.Constants.ADD_TO_SUMMARY_DIV.empty();
JJJ.Constants.ADD_TO_SUMMARY_DIV.show();
JJJ.Constants.ADD_TO_SUMMARY_DIV.append(JJJ.Functions.anchor(
JJJ.Functions._('Add to summary'),
'javascript:JJJ.Functions.addToSummary(unescape("' + escape(s) + '"));',
JJJ.Functions._('Append the proposed summary to the input field below')
));
JJJ.Constants.ADD_TO_SUMMARY_DIV.append(document.createTextNode(': "' + s + '"'));
}
// Re-scan immediately
JJJ.Functions.scan();
};
// The mnemonics of the accepted suggestions are accumulated in JJJ.Constants.appliedSuggestions
// and the user is presented with a sample edit summary. If she accepts it,
// addToSummary() gets called.
ARA_Functions.addToSummary = function (summary) {
var wpSummary = document.getElementById('wpSummary');
if (wpSummary.value != '') {
summary = wpSummary.value + '; ' + summary;
}
if ((wpSummary.maxLength > 0) && (summary.length > wpSummary.maxLength)) {
alert(JJJ.Funtions._(
'Error: If the proposed text is added to the summary, '
+ 'its length will exceed the $1-character maximum by $2 characters.',
/* $1 = */ wpSummary.maxLength,
/* $2 = */ summary.length - wpSummary.maxLength
));
return;
}
wpSummary.value = summary;
JJJ.Constants.ADD_TO_SUMMARY_DIV.hide();
};
// delayScan() postpones the invocation of scan() with a certain timeout.
// If delayScan() is invoked once again during that time, the original
// timeout is cancelled, and another, clean timeout is started from zero.
//
// delayScan() will normally be invoked when a key is pressed---this
// prevents frequent re-scans while the user is typing.
ARA_Functions.delayScan = function () {
if (JJJ.Constants.scanTimeoutId != null) {
clearTimeout(JJJ.Constants.scanTimeoutId);
JJJ.Constants.scanTimeoutId = null;
}
JJJ.Constants.scanTimeoutId = setTimeout(JJJ.Functions.scan, 500);
};
return ARA_Functions;
}
function getARARules()
{
var ARA_Rules = [];
// == Rules ==
// properties:
// * start---the 0-based inclusive index of the first character to be replaced
// * end---analogous to start, but exclusive
// * replacement---the proposed wikitext
// * name---this is what appears at the top of the page
// * description---used as a tooltip for the name of the suggestion
if (!mw.config.get('wgContentLanguage') || mw.config.get('wgContentLanguage') === 'en') { // from this line on, a level of indent is spared
// The rules are stored in an array and are grouped into categories.
//*****************************************************************************************
//*****************************************************************************************
// === Functions ===
/* ITALIC MARKUP HERE */
//***publisher parameter contains italic markup***
ARA_Rules.push(function (s) {
var b = [];
//get indices of all '|publisher='s
var startIndex = 0;
var searchStr = "|publisher=";
var searchStrLen = searchStr.length;
var index, indices = [];
while ((index = s.indexOf(searchStr, startIndex)) > -1)
{
indices.push(index);
startIndex = index + searchStrLen;
}
var indicesLength = indices.length;
for (i = 0; i < indicesLength; i++) //for each |publisher=
{
var pubStartIndex = indices[i] + searchStr.length;
var indexOnward = s.substring(pubStartIndex); //+searchStr.length to exclude "|publisher=\'\'"
//get to the actual beginning of the Publisher if there are spaces or newlines after the "publisher=" and before the start of the text
while ((indexOnward[0] == ' ' || indexOnward[0] == '\n'))
{
indexOnward = indexOnward.substring(1); //cut off the first character
++pubStartIndex;
}
var fullRef = indexOnward;
var fullRefPrevIndex = pubStartIndex - 1;
//indices of various characters in the citation
var firstBracketAfterIndex = indexOnward.includes("}") ? indexOnward.indexOf("}") : s.length;
var firstBarAfterIndex = indexOnward.includes("|") ? indexOnward.indexOf("|") : s.length;
//get to the end of the citation
fullRef = fullRef.substring(0, firstBracketAfterIndex);
//get to the beginning of the citation
while (fullRefPrevIndex >= 0 && s.charAt(fullRefPrevIndex) != '{')
{
fullRef = s.charAt(fullRefPrevIndex) + fullRef; //prepend the character
--fullRefPrevIndex; //decrement index
}
//now we have the full ref.
//get the entire publisher parameter. The parameter should either end with another | or }} for the end of the ref (if not malformed)
//find the nearest delimeter
var cutOffIndex = firstBarAfterIndex;
if (firstBracketAfterIndex < cutOffIndex)
cutOffIndex = firstBracketAfterIndex;
var pub = indexOnward.substring(0, cutOffIndex).trim(); //the pub parameter
//If |publisher= ends with italic markup
if (pub.endsWith('\'\''))
{
b.push({
start: pubStartIndex + pub.length - 2,
end: pubStartIndex + pub.length,
replacement: '',
name: '|publisher= ends with italic markup',
description: '|publisher= ends with italic markup',
});
}
}
return b;
});
ARA_Rules.push(function (s) {
var b = [];
//If the publisher begins with italic markup
var replaceableStrings = ["publisher=\'\'", " publisher = \'\'", " publisher= \'\'", "publisher =\'\'", "publisher= \'\'", " publisher=\'\'"];
for (i = 0; i < replaceableStrings.length; i++)
{
var replaceableString = replaceableStrings[i];
if (s.includes(replaceableString))
{
b.push({
start: s.indexOf(replaceableString),
end: s.indexOf(replaceableString) + replaceableString.length,
replacement: replaceableString.replace("\'\'", ""),
name: '|publisher= begins with italic markup',
description: '|publisher= begins with italic markup',
});
}
}
return b;
});
//***website parameter contains italic markup***
ARA_Rules.push(function (s) {
var b = [];
//get indices of all '|website='s
var startIndex = 0;
var searchStr = "|website=";
var searchStrLen = searchStr.length;
var index, indices = [];
while ((index = s.indexOf(searchStr, startIndex)) > -1)
{
indices.push(index);
startIndex = index + searchStrLen;
}
var indicesLength = indices.length;
for (i = 0; i < indicesLength; i++) //for each |website=
{
var webStartIndex = indices[i] + searchStr.length;
var indexOnward = s.substring(webStartIndex); //+searchStr.length to exclude "|website=\'\'"
//get to the actual beginning of the website if there are spaces or newlines after the "website=" and before the start of the text
while ((indexOnward[0] == ' ' || indexOnward[0] == '\n'))
{
indexOnward = indexOnward.substring(1); //cut off the first character
++webStartIndex;
}
var fullRef = indexOnward;
var fullRefPrevIndex = webStartIndex - 1;
//indices of various characters in the citation
var firstBracketAfterIndex = indexOnward.includes("}") ? indexOnward.indexOf("}") : s.length;
var firstBarAfterIndex = indexOnward.includes("|") ? indexOnward.indexOf("|") : s.length;
//get to the end of the citation
fullRef = fullRef.substring(0, firstBracketAfterIndex);
//get to the beginning of the citation
while (fullRefPrevIndex >= 0 && s.charAt(fullRefPrevIndex) != '{')
{
fullRef = s.charAt(fullRefPrevIndex) + fullRef; //prepend the character
--fullRefPrevIndex; //decrement index
}
//now we have the full ref.
//get the entire website parameter. The parameter should either end with another | or }} for the end of the ref (if not malformed)
//find the nearest delimeter
var cutOffIndex = firstBarAfterIndex;
if (firstBracketAfterIndex < cutOffIndex)
cutOffIndex = firstBracketAfterIndex;
var web = indexOnward.substring(0, cutOffIndex).trim(); //the web parameter
//If the website ends with italic markup
if (web.endsWith('\'\''))
{
b.push({
start: webStartIndex + web.length - 2,
end: webStartIndex + web.length,
replacement: '',
name: '|website= ends with italic markup',
description: '|website= ends with italic markup',
});
}
}
return b;
});
ARA_Rules.push(function (s) {
var b = [];
//If the website begins with italic markup
var replaceableStrings = ["website=\'\'", " website = \'\'", " website= \'\'", "website =\'\'", "website= \'\'", " website=\'\'"];
for (i = 0; i < replaceableStrings.length; i++)
{
var replaceableString = replaceableStrings[i];
if (s.includes(replaceableString))
{
b.push({
start: s.indexOf(replaceableString),
end: s.indexOf(replaceableString) + replaceableString.length,
replacement: replaceableString.replace("\'\'", ""),
name: '|website= begins with italic markup',
description: '|website= begins with italic markup',
});
}
}
return b;
});
//***magazine parameter contains italic markup***
ARA_Rules.push(function (s) {
var b = [];
//get indices of all '|magazine='s
var startIndex = 0;
var searchStr = "|magazine=";
var searchStrLen = searchStr.length;
var index, indices = [];
while ((index = s.indexOf(searchStr, startIndex)) > -1)
{
indices.push(index);
startIndex = index + searchStrLen;
}
var indicesLength = indices.length;
for (i = 0; i < indicesLength; i++) //for each |magazine=
{
var magStartIndex = indices[i] + searchStr.length;
var indexOnward = s.substring(magStartIndex); //+searchStr.length to exclude "|magazine=\'\'"
//get to the actual beginning of the magazine if there are spaces or newlines after the "magazine=" and before the start of the text
while ((indexOnward[0] == ' ' || indexOnward[0] == '\n'))
{
indexOnward = indexOnward.substring(1); //cut off the first character
++magStartIndex;
}
var fullRef = indexOnward;
var fullRefPrevIndex = magStartIndex - 1;
//indices of various characters in the citation
var firstBracketAfterIndex = indexOnward.includes("}") ? indexOnward.indexOf("}") : s.length;
var firstBarAfterIndex = indexOnward.includes("|") ? indexOnward.indexOf("|") : s.length;
//get to the end of the citation
fullRef = fullRef.substring(0, firstBracketAfterIndex);
//get to the beginning of the citation
while (fullRefPrevIndex >= 0 && s.charAt(fullRefPrevIndex) != '{')
{
fullRef = s.charAt(fullRefPrevIndex) + fullRef; //prepend the character
--fullRefPrevIndex; //decrement index
}
//now we have the full ref.
//get the entire magazine parameter. The parameter should either end with another | or }} for the end of the ref (if not malformed)
//find the nearest delimeter
var cutOffIndex = firstBarAfterIndex;
if (firstBracketAfterIndex < cutOffIndex)
cutOffIndex = firstBracketAfterIndex;
var mag = indexOnward.substring(0, cutOffIndex).trim(); //the mag parameter
//If |magazine= ends with italic markup
if (mag.endsWith('\'\''))
{
b.push({
start: magStartIndex + mag.length - 2,
end: magStartIndex + mag.length,
replacement: '',
name: '|magazine= ends with italic markup',
description: '|magazine= ends with italic markup',
});
}
}
return b;
});
ARA_Rules.push(function (s) {
var b = [];
//If the magazine begins with italic markup
var replaceableStrings = ["magazine=\'\'", " magazine = \'\'", " magazine= \'\'", "magazine =\'\'", "magazine= \'\'", " magazine=\'\'"];
for (i = 0; i < replaceableStrings.length; i++)
{
var replaceableString = replaceableStrings[i];
if (s.includes(replaceableString))
{
b.push({
start: s.indexOf(replaceableString),
end: s.indexOf(replaceableString) + replaceableString.length,
replacement: replaceableString.replace("\'\'", ""),
name: '|magazine= begins with italic markup',
description: '|magazine= begins with italic markup',
});
}
}
return b;
});
//***work parameter contains italic markup***
ARA_Rules.push(function (s) {
var b = [];
//get indices of all '|work='s
var startIndex = 0;
var searchStr = "|work=";
var searchStrLen = searchStr.length;
var index, indices = [];
while ((index = s.indexOf(searchStr, startIndex)) > -1)
{
indices.push(index);
startIndex = index + searchStrLen;
}
var indicesLength = indices.length;
for (i = 0; i < indicesLength; i++) //for each |work=
{
var worStartIndex = indices[i] + searchStr.length;
var indexOnward = s.substring(worStartIndex); //+searchStr.length to exclude "|work=\'\'"
//get to the actual beginning of the work if there are spaces or newlines after the "work=" and before the start of the text
while ((indexOnward[0] == ' ' || indexOnward[0] == '\n'))
{
indexOnward = indexOnward.substring(1); //cut off the first character
++worStartIndex;
}
var fullRef = indexOnward;
var fullRefPrevIndex = worStartIndex - 1;
//indices of various characters in the citation
var firstBracketAfterIndex = indexOnward.includes("}") ? indexOnward.indexOf("}") : s.length;
var firstBarAfterIndex = indexOnward.includes("|") ? indexOnward.indexOf("|") : s.length;
//get to the end of the citation
fullRef = fullRef.substring(0, firstBracketAfterIndex);
//get to the beginning of the citation
while (fullRefPrevIndex >= 0 && s.charAt(fullRefPrevIndex) != '{')
{
fullRef = s.charAt(fullRefPrevIndex) + fullRef; //prepend the character
--fullRefPrevIndex; //decrement index
}
//now we have the full ref.
//get the entire work parameter. The parameter should either end with another | or }} for the end of the ref (if not malformed)
//find the nearest delimeter
var cutOffIndex = firstBarAfterIndex;
if (firstBracketAfterIndex < cutOffIndex)
cutOffIndex = firstBracketAfterIndex;
var wor = indexOnward.substring(0, cutOffIndex).trim(); //the wor parameter
//If the work ends with italic markup
if (wor.endsWith('\'\''))
{
b.push({
start: worStartIndex + wor.length - 2,
end: worStartIndex + wor.length,
replacement: '',
name: '|work= ends with italic markup',
description: '|work= ends with italic markup',
});
}
}
return b;
});
ARA_Rules.push(function (s) {
var b = [];
//If the work begins with italic markup
var replaceableStrings = ["work=\'\'", " work = \'\'", " work= \'\'", "work =\'\'", "work= \'\'", " work=\'\'"];
for (i = 0; i < replaceableStrings.length; i++)
{
var replaceableString = replaceableStrings[i];
if (s.includes(replaceableString))
{
b.push({
start: s.indexOf(replaceableString),
end: s.indexOf(replaceableString) + replaceableString.length,
replacement: replaceableString.replace("\'\'", ""),
name: '|work= begins with italic markup',
description: '|work= begins with italic markup',
});
}
}
return b;
});
//***periodical parameter contains italic markup***
ARA_Rules.push(function (s) {
var b = [];
//get indices of all '|periodical='s
var startIndex = 0;
var searchStr = "|periodical=";
var searchStrLen = searchStr.length;
var index, indices = [];
while ((index = s.indexOf(searchStr, startIndex)) > -1)
{
indices.push(index);
startIndex = index + searchStrLen;
}
var indicesLength = indices.length;
for (i = 0; i < indicesLength; i++) //for each |periodical=
{
var perStartIndex = indices[i] + searchStr.length;
var indexOnward = s.substring(perStartIndex); //+searchStr.length to exclude "|periodical=\'\'"
//get to the actual beginning of the periodical if there are spaces or newlines after the "periodical=" and before the start of the text
while ((indexOnward[0] == ' ' || indexOnward[0] == '\n'))
{
indexOnward = indexOnward.substring(1); //cut off the first character
++perStartIndex;
}
var fullRef = indexOnward;
var fullRefPrevIndex = perStartIndex - 1;
//indices of various characters in the citation
var firstBracketAfterIndex = indexOnward.includes("}") ? indexOnward.indexOf("}") : s.length;
var firstBarAfterIndex = indexOnward.includes("|") ? indexOnward.indexOf("|") : s.length;
//get to the end of the citation
fullRef = fullRef.substring(0, firstBracketAfterIndex);
//get to the beginning of the citation
while (fullRefPrevIndex >= 0 && s.charAt(fullRefPrevIndex) != '{')
{
fullRef = s.charAt(fullRefPrevIndex) + fullRef; //prepend the character
--fullRefPrevIndex; //decrement index
}
//now we have the full ref.
//get the entire periodical parameter. The parameter should either end with another | or }} for the end of the ref (if not malformed)
//find the nearest delimeter
var cutOffIndex = firstBarAfterIndex;
if (firstBracketAfterIndex < cutOffIndex)
cutOffIndex = firstBracketAfterIndex;
var per = indexOnward.substring(0, cutOffIndex).trim(); //the per parameter
//If |periodical= ends with italic markup
if (per.endsWith('\'\''))
{
b.push({
start: perStartIndex + per.length - 2,
end: perStartIndex + per.length,
replacement: '',
name: '|periodical= ends with italic markup',
description: '|periodical= ends with italic markup',
});
}
}
return b;
});
ARA_Rules.push(function (s) {
var b = [];
//If the periodical begins with italic markup
var replaceableStrings = ["periodical=\'\'", " periodical = \'\'", " periodical= \'\'", "periodical =\'\'", "periodical= \'\'", " periodical=\'\'"];
for (i = 0; i < replaceableStrings.length; i++)
{
var replaceableString = replaceableStrings[i];
if (s.includes(replaceableString))
{
b.push({
start: s.indexOf(replaceableString),
end: s.indexOf(replaceableString) + replaceableString.length,
replacement: replaceableString.replace("\'\'", ""),
name: '|periodical= begins with italic markup',
description: '|periodical= begins with italic markup',
});
}
}
return b;
});
//***newspaper parameter contains italic markup***
ARA_Rules.push(function (s) {
var b = [];
//get indices of all '|newspaper='s
var startIndex = 0;
var searchStr = "|newspaper=";
var searchStrLen = searchStr.length;
var index, indices = [];
while ((index = s.indexOf(searchStr, startIndex)) > -1)
{
indices.push(index);
startIndex = index + searchStrLen;
}
var indicesLength = indices.length;
for (i = 0; i < indicesLength; i++) //for each |newspaper=
{
var nwpStartIndex = indices[i] + searchStr.length;
var indexOnward = s.substring(nwpStartIndex); //+searchStr.length to exclude "|newspaper=\'\'"
//get to the actual beginning of the newspaper if there are spaces or newlines after the "newspaper=" and before the start of the text
while ((indexOnward[0] == ' ' || indexOnward[0] == '\n'))
{
indexOnward = indexOnward.substring(1); //cut off the first character
++nwpStartIndex;
}
var fullRef = indexOnward;
var fullRefPrevIndex = nwpStartIndex - 1;
//indices of various characters in the citation
var firstBracketAfterIndex = indexOnward.includes("}") ? indexOnward.indexOf("}") : s.length;
var firstBarAfterIndex = indexOnward.includes("|") ? indexOnward.indexOf("|") : s.length;
//get to the end of the citation
fullRef = fullRef.substring(0, firstBracketAfterIndex);
//get to the beginning of the citation
while (fullRefPrevIndex >= 0 && s.charAt(fullRefPrevIndex) != '{')
{
fullRef = s.charAt(fullRefPrevIndex) + fullRef; //prepend the character
--fullRefPrevIndex; //decrement index
}
//now we have the full ref.
//get the entire newspaper parameter. The parameter should either end with another | or }} for the end of the ref (if not malformed)
//find the nearest delimeter
var cutOffIndex = firstBarAfterIndex;
if (firstBracketAfterIndex < cutOffIndex)
cutOffIndex = firstBracketAfterIndex;
var nwp = indexOnward.substring(0, cutOffIndex).trim(); //the nwp parameter
//If the newspaper ends with italic markup
if (nwp.endsWith('\'\''))
{
b.push({
start: nwpStartIndex + nwp.length - 2,
end: nwpStartIndex + nwp.length,
replacement: '',
name: '|newspaper= ends with italic markup',
description: '|newspaper= ends with italic markup',
});
}
}
return b;
});
ARA_Rules.push(function (s) {
var b = [];
//If the newspaper begins with italic markup
var replaceableStrings = ["newspaper=\'\'", " newspaper = \'\'", " newspaper= \'\'", "newspaper =\'\'", "newspaper= \'\'", " newspaper=\'\'"];
for (i = 0; i < replaceableStrings.length; i++)
{
var replaceableString = replaceableStrings[i];
if (s.includes(replaceableString))
{
b.push({
start: s.indexOf(replaceableString),
end: s.indexOf(replaceableString) + replaceableString.length,
replacement: replaceableString.replace("\'\'", ""),
name: '|newspaper= begins with italic markup',
description: '|newspaper= begins with italic markup',
});
}
}
return b;
});
//***journal parameter contains italic markup***
ARA_Rules.push(function (s) {
var b = [];
//get indices of all '|journal='s
var startIndex = 0;
var searchStr = "|journal=";
var searchStrLen = searchStr.length;
var index, indices = [];
while ((index = s.indexOf(searchStr, startIndex)) > -1)
{
indices.push(index);
startIndex = index + searchStrLen;
}
var indicesLength = indices.length;
for (i = 0; i < indicesLength; i++) //for each |journal=
{
var jorStartIndex = indices[i] + searchStr.length;
var indexOnward = s.substring(jorStartIndex); //+searchStr.length to exclude "|journal=\'\'"
//get to the actual beginning of the journal if there are spaces or newlines after the "journal=" and before the start of the text
while ((indexOnward[0] == ' ' || indexOnward[0] == '\n'))
{
indexOnward = indexOnward.substring(1); //cut off the first character
++jorStartIndex;
}
var fullRef = indexOnward;
var fullRefPrevIndex = jorStartIndex - 1;
//indices of various characters in the citation
var firstBracketAfterIndex = indexOnward.includes("}") ? indexOnward.indexOf("}") : s.length;
var firstBarAfterIndex = indexOnward.includes("|") ? indexOnward.indexOf("|") : s.length;
//get to the end of the citation
fullRef = fullRef.substring(0, firstBracketAfterIndex);
//get to the beginning of the citation
while (fullRefPrevIndex >= 0 && s.charAt(fullRefPrevIndex) != '{')
{
fullRef = s.charAt(fullRefPrevIndex) + fullRef; //prepend the character
--fullRefPrevIndex; //decrement index
}
//now we have the full ref.
//get the entire journal parameter. The parameter should either end with another | or }} for the end of the ref (if not malformed)
//find the nearest delimeter
var cutOffIndex = firstBarAfterIndex;
if (firstBracketAfterIndex < cutOffIndex)
cutOffIndex = firstBracketAfterIndex;
var jor = indexOnward.substring(0, cutOffIndex).trim(); //the jor parameter
//If |journal= ends with italic markup
if (jor.endsWith('\'\''))
{
b.push({
start: jorStartIndex + jor.length - 2,
end: jorStartIndex + jor.length,
replacement: '',
name: '|journal= ends with italic markup',
description: '|journal= ends with italic markup',
});
}
}
return b;
});
ARA_Rules.push(function (s) {
var b = [];
//If the journal begins with italic markup
var replaceableStrings = ["journal=\'\'", " journal = \'\'", " journal= \'\'", "journal =\'\'", "journal= \'\'", " journal=\'\'"];
for (i = 0; i < replaceableStrings.length; i++)
{
var replaceableString = replaceableStrings[i];
if (s.includes(replaceableString))
{
b.push({
start: s.indexOf(replaceableString),
end: s.indexOf(replaceableString) + replaceableString.length,
replacement: replaceableString.replace("\'\'", ""),
name: '|journal= begins with italic markup',
description: '|journal= begins with italic markup',
});
}
}
return b;
});
/* BOLD MARKUP HERE */
//***publisher parameter contains bold markup***
ARA_Rules.push(function (s) {
var b = [];
//get indices of all '|publisher='s
var startIndex = 0;
var searchStr = "|publisher=";
var searchStrLen = searchStr.length;
var index, indices = [];
while ((index = s.indexOf(searchStr, startIndex)) > -1)
{
indices.push(index);
startIndex = index + searchStrLen;
}
var indicesLength = indices.length;
for (i = 0; i < indicesLength; i++) //for each |publisher=
{
var pubStartIndex = indices[i] + searchStr.length;
var indexOnward = s.substring(pubStartIndex); //+searchStr.length to exclude "|publisher=\'\'\'"
//get to the actual beginning of the Publisher if there are spaces or newlines after the "publisher=" and before the start of the text
while ((indexOnward[0] == ' ' || indexOnward[0] == '\n'))
{
indexOnward = indexOnward.substring(1); //cut off the first character
++pubStartIndex;
}
var fullRef = indexOnward;
var fullRefPrevIndex = pubStartIndex - 1;
//indices of various characters in the citation
var firstBracketAfterIndex = indexOnward.includes("}") ? indexOnward.indexOf("}") : s.length;
var firstBarAfterIndex = indexOnward.includes("|") ? indexOnward.indexOf("|") : s.length;
//get to the end of the citation
fullRef = fullRef.substring(0, firstBracketAfterIndex);
//get to the beginning of the citation
while (fullRefPrevIndex >= 0 && s.charAt(fullRefPrevIndex) != '{')
{
fullRef = s.charAt(fullRefPrevIndex) + fullRef; //prepend the character
--fullRefPrevIndex; //decrement index
}
//now we have the full ref.
//get the entire publisher parameter. The parameter should either end with another | or }} for the end of the ref (if not malformed)
//find the nearest delimeter
var cutOffIndex = firstBarAfterIndex;
if (firstBracketAfterIndex < cutOffIndex)
cutOffIndex = firstBracketAfterIndex;
var pub = indexOnward.substring(0, cutOffIndex).trim(); //the pub parameter
//If |publisher= ends with bold markup
if (pub.endsWith('\'\'\''))
{
b.push({
start: pubStartIndex + pub.length - 2,
end: pubStartIndex + pub.length,
replacement: '',
name: '|publisher= ends with bold markup',
description: '|publisher= ends with bold markup',
});
}
}
return b;
});
ARA_Rules.push(function (s) {
var b = [];
//If the publisher begins with bold markup
var replaceableStrings = ["publisher=\'\'\'", " publisher = \'\'\'", " publisher= \'\'\'", "publisher =\'\'\'", "publisher= \'\'\'", " publisher=\'\'\'"];
for (i = 0; i < replaceableStrings.length; i++)
{
var replaceableString = replaceableStrings[i];
if (s.includes(replaceableString))
{
b.push({
start: s.indexOf(replaceableString),
end: s.indexOf(replaceableString) + replaceableString.length,
replacement: replaceableString.replace("\'\'\'", ""),
name: '|publisher= begins with bold markup',
description: '|publisher= begins with bold markup',
});
}
}
return b;
});
//***website parameter contains bold markup***
ARA_Rules.push(function (s) {
var b = [];
//get indices of all '|website='s
var startIndex = 0;
var searchStr = "|website=";
var searchStrLen = searchStr.length;
var index, indices = [];
while ((index = s.indexOf(searchStr, startIndex)) > -1)
{
indices.push(index);
startIndex = index + searchStrLen;
}
var indicesLength = indices.length;
for (i = 0; i < indicesLength; i++) //for each |website=
{
var webStartIndex = indices[i] + searchStr.length;
var indexOnward = s.substring(webStartIndex); //+searchStr.length to exclude "|website=\'\'\'"
//get to the actual beginning of the website if there are spaces or newlines after the "website=" and before the start of the text
while ((indexOnward[0] == ' ' || indexOnward[0] == '\n'))
{
indexOnward = indexOnward.substring(1); //cut off the first character
++webStartIndex;
}
var fullRef = indexOnward;
var fullRefPrevIndex = webStartIndex - 1;
//indices of various characters in the citation
var firstBracketAfterIndex = indexOnward.includes("}") ? indexOnward.indexOf("}") : s.length;
var firstBarAfterIndex = indexOnward.includes("|") ? indexOnward.indexOf("|") : s.length;
//get to the end of the citation
fullRef = fullRef.substring(0, firstBracketAfterIndex);
//get to the beginning of the citation
while (fullRefPrevIndex >= 0 && s.charAt(fullRefPrevIndex) != '{')
{
fullRef = s.charAt(fullRefPrevIndex) + fullRef; //prepend the character
--fullRefPrevIndex; //decrement index
}
//now we have the full ref.
//get the entire website parameter. The parameter should either end with another | or }} for the end of the ref (if not malformed)
//find the nearest delimeter
var cutOffIndex = firstBarAfterIndex;
if (firstBracketAfterIndex < cutOffIndex)
cutOffIndex = firstBracketAfterIndex;
var web = indexOnward.substring(0, cutOffIndex).trim(); //the web parameter
//If the website ends with bold markup
if (web.endsWith('\'\'\''))
{
b.push({
start: webStartIndex + web.length - 2,
end: webStartIndex + web.length,
replacement: '',
name: '|website= ends with bold markup',
description: '|website= ends with bold markup',
});
}
}
return b;
});
ARA_Rules.push(function (s) {
var b = [];
//If the website begins with bold markup
var replaceableStrings = ["website=\'\'\'", " website = \'\'\'", " website= \'\'\'", "website =\'\'\'", "website= \'\'\'", " website=\'\'\'"];
for (i = 0; i < replaceableStrings.length; i++)
{
var replaceableString = replaceableStrings[i];
if (s.includes(replaceableString))
{
b.push({
start: s.indexOf(replaceableString),
end: s.indexOf(replaceableString) + replaceableString.length,
replacement: replaceableString.replace("\'\'\'", ""),
name: '|website= begins with bold markup',
description: '|website= begins with bold markup',
});
}
}
return b;
});
/* TECHNICAL - HELPS SCRIPT FUNCTION */
//***unnecessary whitespace in citation***
ARA_Rules.push(function (s) {
var b = [];
var replaceableStrings = [" publisher=","publisher ="," publisher =", " website=","website ="," website =", " magazine=","magazine ="," magazine =", " work=","work ="," work =", " periodical=","periodical ="," periodical =", " newspaper=","newspaper ="," newspaper =", " journal=", "journal ="," journal= "];
for (i = 0; i < replaceableStrings.length; i++)
{
var replaceableString = replaceableStrings[i];
if (s.includes(replaceableString))
{
b.push({
start: s.indexOf(replaceableString),
end: s.indexOf(replaceableString) + replaceableString.length,
replacement: replaceableString.replace(" ", ""),
name: 'extra whitespace in citation (' + replaceableString + ')',
description: 'extra whitespace in citation (' + replaceableString + ')'
});
}
}
return b;
});
} // end if mw.config.get('wgContentLanguage') === 'en'
return ARA_Rules;
}
// </nowiki>