// <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>