// <nowiki>// Everything is encapsulated in a private namespace object---``JJJ'':var JJJ = JJJ || {};$(document).ready(function() {//initialize ConstantsJJJ.Constants = getARAConstants();//only execute on the edit pageif (!JJJ.Constants.IS_EDIT_PAGE || JJJ.Constants.IS_JS_PAGE || JJJ.Constants.ARTICLE_TEXT_BOX_ELEMENT == null)return;//init functions and rulesJJJ.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 nowJJJ.Functions.observeWikiText(JJJ.Constants.delayScan); // ... and every time the user pauses typing});function getARAConstants(){var ARA_Constants = ARA_Constants || {};//article text box elementARA_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 sectionARA_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 summaryARA_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 itARA_Constants.BIG_THRESHOLD = 100 * 1024;ARA_Constants.isBigScanConfirmed = false; // is the warning about a big article confirmedARA_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 functionvar _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 propertyif (ta.scrollTop != yOffset) {// todo: Warn the user or apply a workaround}} else {ta.scrollTop = 0;}} else {// IE incorrectly counts '\r\n' as a signle characterstart -= 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 freturn 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 compatibilityalert(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 compatibilityARA_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 textvar s = JJJ.Functions.getWikiText();//determine if we actually need to scanif ((s === JJJ.Constants.scannedText) && !force)return; // Nothing to do, we've already scanned the very same textJJJ.Constants.scannedText = s;//remove all current suggestionsJJJ.Constants.SUGGESTION_BOX_DIV.empty();// Warn about scanning a big articleif ((s && 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 pageif (( 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 suggestionsJJJ.Constants.suggestions = JJJ.Functions.getSuggestions(s);//if there aren't any suggestions, say soif (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 linkif (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 twicefor (var i = 0; i < JJJ.Rules.length; i++) //for each rule{var a = JJJ.Rules[i](s); //execute rulefor (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 suggestionsmissingRefGroupSuggestions.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 popupARA_Functions.showSuggestion = function (k) {if (JJJ.Functions.getWikiText() != JJJ.Constants.scannedText) {// The text has changed - just do another scan and don't change selectionJJJ.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 helpvar 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, returnif (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 sectionvar 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 [[Template:Broken ref/cite error list|$1]] using [[User:TheJJJunk/ARA|ARA]]',s.substring(2) ); if (s == "fixed [[Template:Broken ref/cite error list|missing Name in Persondata]] using [[User:TheJJJunk/ARA|ARA]]") s = "added [[Wikipedia:PERSON#Name and titles|missing Name in Persondata]] using [[User:TheJJJunk/ARA|ARA]]"; else if (s == "fixed [[Template:Broken ref/cite error list|empty Persondata template]] using [[User:TheJJJunk/ARA|ARA]]") s = "expanded [[Wikipedia:PERSON|empty Persondata template]] using [[User:TheJJJunk/ARA|ARA]]"; else if (s.indexOf("references in Portal page]] using [[User:TheJJJunk/ARA|ARA]]") > -1) s = "removed [[Wikipedia talk:Portal guidelines#References in portals|references from Portal page]] using [[User:TheJJJunk/ARA|ARA]]"; else if (s == "fixed [[Template:Broken ref/cite error list|{{Reflist}} in Portal page]] using [[User:TheJJJunk/ARA|ARA]]") s = "removed [[Wikipedia talk:Portal guidelines#References in portals|{{Reflist}} from Portal page]] using [[User:TheJJJunk/ARA|ARA]]"; // Render in DOMJJJ.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 immediatelyJJJ.Functions.scan();};// if a suggestion has two 'fix' options, the second option will be handled hereARA_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, returnif (suggestion.replacement2 == null) { return;}//otherwise, if we are executing JS, do soelse 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 sectionvar 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 [[Template:Broken ref/cite error list|$1]] using [[User:TheJJJunk/ARA|ARA]]',s.substring(2) ); if (s == "fixed [[Template:Broken ref/cite error list|missing Name in Persondata]] using [[User:TheJJJunk/ARA|ARA]]") s = "added [[Wikipedia:PERSON#Name and titles|missing Name in Persondata]] using [[User:TheJJJunk/ARA|ARA]]"; else if (s == "fixed [[Template:Broken ref/cite error list|empty Persondata template]] using [[User:TheJJJunk/ARA|ARA]]") s = "expanded [[Wikipedia:PERSON|empty Persondata template]] using [[User:TheJJJunk/ARA|ARA]]"; else if (s.indexOf("references in Portal page]] using [[User:TheJJJunk/ARA|ARA]]") > -1) s = "removed [[Wikipedia talk:Portal guidelines#References in portals|references from Portal page]] using [[User:TheJJJunk/ARA|ARA]]"; else if (s == "fixed [[Template:Broken ref/cite error list|{{Reflist}} in Portal page]] using [[User:TheJJJunk/ARA|ARA]]") s = "removed [[Wikipedia talk:Portal guidelines#References in portals|{{Reflist}} from Portal page]] using [[User:TheJJJunk/ARA|ARA]]"; // Render in DOMJJJ.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 immediatelyJJJ.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 fixablereturn;}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 sectionvar 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 [[Template:Broken ref/cite error list|$1]] using [[User:TheJJJunk/ARA|ARA]]',s.substring(2) ); if (s == "fixed [[Template:Broken ref/cite error list|missing Name in Persondata]] using [[User:TheJJJunk/ARA|ARA]]") s = "added [[Wikipedia:PERSON#Name and titles|missing Name in Persondata]] using [[User:TheJJJunk/ARA|ARA]]"; else if (s == "fixed [[Template:Broken ref/cite error list|empty Persondata template]] using [[User:TheJJJunk/ARA|ARA]]") s = "expanded [[Wikipedia:PERSON|empty Persondata template]] using [[User:TheJJJunk/ARA|ARA]]"; else if (s.indexOf("references in Portal page]] using [[User:TheJJJunk/ARA|ARA]]") > -1) s = "removed [[Wikipedia talk:Portal guidelines#References in portals|references from Portal page]] using [[User:TheJJJunk/ARA|ARA]]"; else if (s == "fixed [[Template:Broken ref/cite error list|{{Reflist}} in Portal page]] using [[User:TheJJJunk/ARA|ARA]]") s = "removed [[Wikipedia talk:Portal guidelines#References in portals|{{Reflist}} from Portal page]] using [[User:TheJJJunk/ARA|ARA]]"; // Render in DOMJJJ.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 immediatelyJJJ.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 suggestionif (!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 ===//***missing {{Reflist}}***ARA_Rules.push(function (s) {var Re = "{{Reflist";var re = "{{reflist";var ore = "<references />";var oree = "<references/>";var b = []; var sstart; var eend; var rreplacement; var mySection; var name = document.URL; if (name.indexOf("section=") < 0) { if (s && s.indexOf("<ref") > -1 && s.indexOf(re) < 0 && s.indexOf(Re) < 0 && s.indexOf(ore) < 0 && s.indexOf(oree) < 0 && s.indexOf("{{reflist))") < 0 && s.indexOf("{{relist}}") < 0 && s.indexOf("{{Reflist|refs=") < 0 && s.indexOf("{{reflist|refs=") < 0 && document.URL.indexOf("title=Portal:") < 0) //(don't add reflist to portals) { if (s.indexOf("==References==") > -1 || s.indexOf("== References ==") > -1 || s.indexOf("==Sources==") > -1 || s.indexOf("== Sources ==") > -1) { if (s.indexOf("==References==") > -1){mySection = "==References=="; sstart = s.indexOf(mySection); eend = sstart + 14;} else if (s.indexOf("== References ==") > -1){mySection = "== References ==";sstart=s.indexOf(mySection);eend = sstart + 16;} else if (s.indexOf("==Sources==") > -1){mySection = "==Sources==";sstart=s.indexOf(mySection);eend=sstart+11;} else {mySection = "== Sources ==";sstart=s.indexOf(mySection);eend=sstart+13;} rreplacement = "==References==\n{{Reflist}}"; } else if (s.indexOf("==Further reading==") > -1) { sstart = s.indexOf("==Further reading=="); eend = sstart + 19; rreplacement = "==References==\n{{Reflist}}\n\n==Further reading=="; } else if (s.indexOf("==External links==") > -1 || s.indexOf("== External links ==")> -1 || s.indexOf("==External links ==") >-1 || s.indexOf("== External links==") > -1|| s.indexOf("== External Links ==")> -1 || s.indexOf("==External Links==") > -1) { if (s.indexOf("==External links==") > -1){mySection = "==External links=="; sstart = s.indexOf(mySection); eend = sstart+18;} else if(s.indexOf("== External links ==")>-1){mySection="== External links ==";sstart=s.indexOf(mySection);eend= sstart + 20;} else if(s.indexOf("== External links==")>-1){mySection="== External links==";sstart=s.indexOf(mySection);eend=sstart+19;} else if(s.indexOf("== External Links ==")>-1){mySection="== External Links ==";sstart=s.indexOf(mySection);eend= sstart + 20;} else if(s.indexOf("==External Links==")>-1){mySection="==External Links==";sstart=s.indexOf(mySection);eend=sstart+18;} else {mySection = "==External links =="; sstart = s.indexOf(mySection); eend = sstart+19;} rreplacement = "==References==\n{{Reflist}}\n\n==External links=="; } else if (s.indexOf("==See also==") > -1 || s.indexOf("== See also ==") > -1) { var seeAlso; if (s.indexOf("==See also==") > 0) seeAlso = "==See also=="; else seeAlso = "== See also =="; var afterSeeAlso = s.split(seeAlso)[1]; if (s.indexOf("==See also==\n{{") > 0)afterSeeAlso = afterSeeAlso.slice(afterSeeAlso.indexOf("}}")); while ((afterSeeAlso.indexOf("[[") < afterSeeAlso.indexOf("{{") || afterSeeAlso.indexOf("{{") == -1) && (afterSeeAlso.indexOf("[[") < afterSeeAlso.indexOf("[[Category:") || afterSeeAlso.indexOf("[[Category:") == -1)) { afterSeeAlso = afterSeeAlso.slice(afterSeeAlso.indexOf("]]")+2); } sstart = s.indexOf(afterSeeAlso); eend = sstart; rreplacement = "\n\n==References==\n{{Reflist}}"; } else if (s.indexOf("{{Authority control") > -1) { sstart = s.indexOf("{{Authority control"); var completeTemplate = s.split("{{Authority control")[1]; completeTemplate = completeTemplate.slice(completeTemplate.indexOf("}}" + 2)); var completeTemplateLoc = completeTemplate.indexOf("}}"); eend = sstart + completeTemplateLoc; rreplacement = "==References==\n{{Reflist}}" + completeTemplate; } else if (s.indexOf("{{DEFAULTSORT") > -1) { if (s.indexOf("}}\n\n{{DEFAULTSORT") > -1 || s.indexOf("}}\n{{DEFAULTSORT") > -1) { if (s.indexOf("}}\n\n{{DEFAULTSORT") > -1) mySection = "}}\n\n{{DEFAULTSORT"; else mySection = "}}\n{{DEFAULTSORT"; var completeTemplate = mySection; while (s.charAt(s.indexOf(completeTemplate)-1) != '{') completeTemplate = s.charAt(s.indexOf(completeTemplate)-1) + completeTemplate; completeTemplate = "{{" + completeTemplate; completeTemplate = completeTemplate.split("}}")[0]; completeTemplate = completeTemplate + "}}"; while (s.indexOf("}}\n" + completeTemplate) > -1 || s.indexOf("}}\n\n" + completeTemplate) > -1) { var secondTemplate = s.split("\n"+completeTemplate)[0];secondTemplate = secondTemplate.slice(secondTemplate.lastIndexOf("{{")); completeTemplate = secondTemplate+"\n"+completeTemplate; } sstart = s.indexOf(completeTemplate); eend = sstart + completeTemplate.length; rreplacement = "==References==\n{{Reflist}}\n\n" + completeTemplate; } else { sstart = s.indexOf("{{DEFAULTSORT"); var completeTemplate = s.split("{{DEFAULTSORT")[1]; completeTemplate = completeTemplate.slice(completeTemplate.indexOf("}}" + 2)); var completeTemplateLoc = completeTemplate.indexOf("}}"); eend = sstart + completeTemplateLoc; rreplacement = "==References==\n{{Reflist}}" + completeTemplate; } } else if (s.indexOf("[[Category:") > -1) { if (s.indexOf("}}\n\n[[Category:") > -1 || s.indexOf("}}\n[[Category:") > -1) { if (s.indexOf("}}\n\n[[Category:") > -1) mySection = "}}\n\n[[Category:"; else mySection = "}}\n[[Category:"; var completeTemplate = mySection; while (s.charAt(s.indexOf(completeTemplate)-1) != '{') completeTemplate = s.charAt(s.indexOf(completeTemplate)-1) + completeTemplate; completeTemplate = "{{" + completeTemplate; completeTemplate = completeTemplate.split("}}")[0]; completeTemplate = completeTemplate + "}}"; while (s.indexOf("}}\n" + completeTemplate) > -1 || s.indexOf("}}\n\n" + completeTemplate) > -1) { var secondTemplate = s.split("\n"+completeTemplate)[0];secondTemplate = secondTemplate.slice(secondTemplate.lastIndexOf("{{")); completeTemplate = secondTemplate+"\n"+completeTemplate; } sstart = s.indexOf(completeTemplate); eend = sstart + completeTemplate.length; rreplacement = "==References==\n{{Reflist}}\n\n" + completeTemplate; } else { sstart = s.indexOf("[[Category:"); var completeTemplate = s.slice(s.indexOf("[[Category:")); completeTemplate = completeTemplate.slice(completeTemplate.indexOf("}}" + 2)); var completeTemplateLoc = completeTemplate.indexOf("}}"); eend = sstart + completeTemplateLoc; rreplacement = "==References==\n{{Reflist}}" + completeTemplate; } } else if (s.indexOf("{{uncat") > -1) { sstart = s.indexOf("{{uncat") - 1; eend = s.indexOf("{{uncat") - 1; rreplacement = "\n==References==\n{{Reflist}}\n"; } else if (s.indexOf("stub}}") > -1) { var stub = "stub}}"; while (s.charAt(s.indexOf(stub)-1) != '{') stub = s.charAt(s.indexOf(stub)-1) + stub; stub = "{{" + stub; sstart = s.indexOf(stub) -1; eend = s.indexOf(stub) -1; rreplacement = "\n==References==\n{{Reflist}}\n"; } else { sstart = s.length; eend = s.length; rreplacement = "\n==References==\n{{Reflist}}\n"; } b.push({start: sstart,end: eend,replacement: rreplacement, name: 'missing {{Reflist}}',description: '<ref></ref> tags are present, but the reference list template is missing.'});} } return b;});//***inapplicable tag***ARA_Rules.push(function (s) {var b = []; var sstart; var eend; var rreplacement; //if there is an "Unreferenced" tag and there are references presentif ( (s.indexOf("{{no footnotes|date") > -1 || s.indexOf("{{unreferenced|date") > -1 || s.indexOf("{{Unreferenced|date") > -1 || s.indexOf("{{unsourced|date") > -1) && (s.indexOf("{{Reflist") > -1 || s.indexOf("{{reflist") > -1) && s.indexOf("<ref") > -1 ){ var unreferencedTemplate; if (s.indexOf("{{no footnotes|date") > -1) unreferencedTemplate = "{{no footnotes|date"; else if (s.indexOf("{{unreferenced|date") > -1) unreferencedTemplate = "{{unreferenced|date"; else if (s.indexOf("{{Unreferenced|date") > -1) unreferencedTemplate = "{{Unreferenced|date"; else unreferencedTemplate = "{{unsourced|date"; //build the rest of the tag until we hit the end of the template or the end of the article text while (!unreferencedTemplate.endsWith('}}') && unreferencedTemplate.length + 1 < s.length)unreferencedTemplate += s.charAt(s.indexOf(unreferencedTemplate) + unreferencedTemplate.length); //if the template is on its own line, remove the entire line if (s.charAt(s.indexOf(unreferencedTemplate) - 1) === "\n" && s.charAt(s.indexOf(unreferencedTemplate) + unreferencedTemplate.length) === '\n') { unreferencedTemplate = "\n" + unreferencedTemplate + "\n"; } sstart = s.indexOf(unreferencedTemplate); eend = sstart + unreferencedTemplate.length; b.push({ start: sstart,end: eend,replacement: '', name: 'inapplicable tag',description: 'There is an unreferenced tag on the page, but <ref> tags are present. It may no longer apply.' }); }return b;});//***unnecessary reference groups AND missing reference groups***////We can use the same function to find both the unnecessary ref groups and the missing ones. Once we've found them, we can decide which// category they fall underARA_Rules.push(function (s) {var b = []; var noteGroups = ["n", "N", "note", "Note", "nb", "lower-alpha", "upper-alpha"]; //get indices of all 'group='s var startIndex = 0; var searchStr = "group="; var searchStrLen = searchStr.length;var index = null;var 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 group={var groupIndex = indices[i]; //index of "group="var mySectionPrevIndex = groupIndex - 1;var groupNameIndex = groupIndex + 6; //after "group=";var mySection = s.substring(groupNameIndex);var groupAndName = s.substring(groupIndex); //contains "group=<name>..."if (groupAndName.includes(">")) //if the ref isn't malformedgroupAndName = groupAndName.substring(0, groupAndName.indexOf(">")) + ">"; //cut away anything after end of ref, and re-add gt//else, the ref is malformedvar fullRef = groupAndName;var cutOffQuote = false;if (mySection[0] == '"') //if quote following group declaration{mySection = mySection.substring(1); //cut that character outcutOffQuote = true;}//find the end of the group name// : group=sampleName> ... // : group=sampleName /> ... // : group="sampleName" ... // : group=sampleName name="winner" ... // : Note: group=sample}} // : Note: group=sample|name=sampleName... var firstBracketAfterIndex = mySection.includes(">") ? mySection.indexOf(">") : s.length;var firstSlashAfterIndex = mySection.includes("/") ? mySection.indexOf("/") : s.length;var firstQuoteAfterIndex = mySection.includes("\"") ? mySection.indexOf("\"") : s.length;var nameEqualsAfterIndex = mySection.includes(" name=") ? mySection.indexOf(" name=") : s.length;var spaceAfterIndex = mySection.includes(" ") && !cutOffQuote ? mySection.indexOf(" ") : s.length;var bracketAfterIndex = mySection.includes("}") ? mySection.indexOf("}") : s.length;var vBarAfterIndex = mySection.includes("|") ? mySection.indexOf("|") : s.length;var cutOffIndex = firstBracketAfterIndex;if (firstSlashAfterIndex < cutOffIndex) cutOffIndex = firstSlashAfterIndex;if (firstQuoteAfterIndex < cutOffIndex) cutOffIndex = firstQuoteAfterIndex; if (nameEqualsAfterIndex < cutOffIndex) cutOffIndex = nameEqualsAfterIndex; if (spaceAfterIndex < cutOffIndex) cutOffIndex = spaceAfterIndex; if (bracketAfterIndex < cutOffIndex) cutOffIndex = bracketAfterIndex; if (vBarAfterIndex < cutOffIndex) cutOffIndex = vBarAfterIndex;var groupName = mySection.substring(0, cutOffIndex); //the name of the reference group//if we already have a Reflist tag with this group name, skip this refvar refLists = ["{{Reflist|group=" + groupName + "}}","{{Reflist|group=" + groupName + "|","{{reflist|group=" + groupName + "}}","{{reflist|group=" + groupName + "|",'{{Reflist|group="' + groupName + '"','{{reflist|group="' + groupName + '"',];var listAlreadyPresent = false;for (j = 0; j < refLists.length; j++){if (s.includes(refLists[j])) {listAlreadyPresent = true;break;}}if (listAlreadyPresent)continue; //otherwise, if this is a group that we WANT to add a reflist for if (noteGroups.includes(groupName)) { var startIndex = null; var endIndex = null; var replacementText = null; var suggestionName = 'missing reference groups (' + groupName + ')'; var includesNotesHdr = false; //determine where to place the new list. We'll either be adding it to an existing Notes section or creating a new Notes section. // In certain cases, the Notes section may contain a ;Footnotes sub-heading, in which case we'll want to put the new list beneath that // sub-heading. // If we're creating a new Notes section, we'll want to put the new section above the References section var notesHeaderVariations = ["==Notes==", "== Notes == "]; for (j = 0; j < notesHeaderVariations.length; j++) { var notesHeader = notesHeaderVariations[j]; if (s.includes(notesHeader)) { var notesHeaderWithFootnotesSubHeading = notesHeader + "\n;Footnotes\n"; //determine if the section contains the ;Footnotes sub-heading if (s.includes(notesHeaderWithFootnotesSubHeading)) startIndex = s.indexOf(notesHeaderWithFootnotesSubHeading) + notesHeaderWithFootnotesSubHeading.length; else //no Footnotes sub-heading startIndex = s.indexOf(notesHeader) + notesHeader.length; endIndex = startIndex; replacementText = "{{Reflist|group=" + groupName + "}}\n"; includesNotesHdr = true; break; } } //otherwise, there is no Notes header, so we'll be creating one if (!includesNotesHdr) { referencesHeader = "==References=="; if (!s.includes(referencesHeader)) referencesHeader = "== References =="; startIndex = s.indexOf(referencesHeader) - 1; endIndex = startIndex; replacementText = "\n==Notes==\n{{Reflist|group=" + groupName + "}}\n"; } b.push({start: startIndex,end: endIndex,replacement: replacementText,name: suggestionName,description: suggestionName}); } else //the ref group is "unnecessary" { //else, this is a group we want to replace. //Check to see if the reference already has a name. If it doesn't, add one. If it does, just remove the group //get to the beginning of the reference while (mySectionPrevIndex >= 0 && s.charAt(mySectionPrevIndex) != '<') { fullRef = s.charAt(mySectionPrevIndex) + fullRef; //prepend the character --mySectionPrevIndex; //decrement index } //now at the beginning of the reference (or the page, if the reference was malformed) // and we already have to the end of the ref, so we have the full ref fullRef = "<" + fullRef; //re-build mySection with the group name intact, since we removed it before var addBackNum = cutOffQuote ? 7 : 6; mySection = s.substring(groupIndex, groupIndex + addBackNum + cutOffIndex); //whether or not the ref contains "name=" already, we'll start at the same placevar startReplaceIndex = s.indexOf(fullRef) + fullRef.indexOf("group="); //start at the beginning of the "group=" //if there is already a name for this ref, we want to remove the entire "group=<name>".//We need to also remove any quotes around the group name if (fullRef.includes("name=")) {var endReplaceIndex = startReplaceIndex + addBackNum + groupName.length; //end after the group nameif (cutOffQuote) //if we removed a quote earlier, then we know we need to also remove quotesendReplaceIndex += 1; //add to include extra quote //if there are spaces at both ends of the section we're removing, take away one of the spaces so we aren't left with two consecutive spacesif (s.charAt(startReplaceIndex-1) == ' ' && s.charAt(endReplaceIndex) == ' ')++endReplaceIndex;//if the ref group is at the end of an open ref, check to see if we should remove an extra space preceding the groupif (s.charAt(startReplaceIndex-1) == ' ' && s.charAt(endReplaceIndex) == '>')--startReplaceIndex;b.push({start: startReplaceIndex,end: endReplaceIndex,replacement: "", name: 'unnecessary reference groups (' + groupName + ')',description: 'Reference groups in citations are causing an error.'}); } else //there isn't already a name, so just replace "group=" with "name=" { var endReplaceIndex = startReplaceIndex + 5; //+ "group"b.push({start: startReplaceIndex,end: endReplaceIndex,replacement: "name", name: 'unnecessary reference groups (' + groupName + ')',description: 'Reference groups in citations are causing an error.'}); } }}return b;});//***missing notelist***ARA_Rules.push(function(s) { var b = [];var theMatchWeFound = null;//potential matchesvar potentialMatchesWithReplacements = [{ref: "{{efn-ua",list: ["{{notelist-ua}}", "{{Notelist-ua}}"],name: "missing notelist-ua"},{ref: "{{efn-lr",list: ["{{notelist-lr}}", "{{Notelist-lr}}"],name: "missing notelist-lr"},{ref: "{{efn|",list: ["{{notelist}}", "{{Notelist}}"],name: "missing notelist"},{ref: "group=lower-alpha",list: ["{{notelist}}", "{{Notelist}}"],name: "missing notelist"}];//look for matchesfor (i = 0; i < potentialMatchesWithReplacements.length; i++){//if we've already found a match, breakif (theMatchWeFound !== null)break;var thisMatch = potentialMatchesWithReplacements[i];//determine if any of the lists are already present; if any are present, we do not have a matchvar alreadyHasList = false;for (j = 0; j < thisMatch.list.length; j++){if (s.includes(thisMatch.list[j])){alreadyHasList = true;break;}}if (alreadyHasList)continue;//look for the ref (remember that we've already checked above to determine if the article contains the list)if (s.includes(thisMatch.ref)){theMatchWeFound = {ref: thisMatch.ref,list: thisMatch.list[0],name: thisMatch.name};}}//if we found a match, determine the change we need to make and where we need to make itif (theMatchWeFound !== null){var startIndex = null;var endIndex = null;var replacementText = null;var containsNotesHdr = false;//if the article contains the ==Notes== header, we simply want to add the notelist to the Notes sectionvar notesHdrVariations = ["==Notes==", "== Notes =="];for (i = 0; i < notesHdrVariations.length; i++){var notesHdr = notesHdrVariations[i];if (s.includes(notesHdr)){startIndex = s.indexOf(notesHdr) + notesHdr.length;endIndex = startIndex;replacementText = "\n" + theMatchWeFound.list;containsNotesHdr = true;break;}}//if the article does NOT contain the Notes header, then it is assumed that it contains the References header (one of the two variations)if (!containsNotesHdr){var refHdrSyntax = "==References==";if (!s.includes(refHdrSyntax)) refHdrSyntax = "== References =="; startIndex = s.indexOf(refHdrSyntax);endIndex = s.indexOf(refHdrSyntax) + refHdrSyntax.length;replacementText = "==Notes==\n" + theMatchWeFound.list + "\n\n" + refHdrSyntax;}//push result b.push({start: startIndex,end: endIndex,replacement: replacementText,name: theMatchWeFound.name,description: theMatchWeFound.name });}return b;});//***invalid <ref></ref> tags***ARA_Rules.push(function (s) {var b = []; var sstart; var eend; var rreplacement; var mySection; var theList;if (s.indexOf("{{Reflist|refs=") < 0 && // limiting factors s.indexOf("{{reflist|refs=") < 0 && s.indexOf("<ref") > -1 && ( s.indexOf("{{Reflist") > -1 || s.indexOf("{{reflist") > -1 || s.indexOf("<references/>") > -1 || s.indexOf("<references />") > -1 ) ) { if (s.indexOf("{{Reflist") > -1) theList = "{{Reflist"; else if (s.indexOf("{{reflist") > -1) theList = "{{reflist"; // defining type of reflist else if (s.indexOf("<references/>") >-1) theList = "<references/>"; else theList = "<references />"; if (s.lastIndexOf("<ref>") > s.indexOf(theList)) // if there is "<ref>" below reflist { mySection = s.split(theList)[1]; // mySection = everything after reflist mySection = mySection.slice(mySection.indexOf("<ref>")); // mySection starts at the <ref> tag if (mySection.indexOf("</ref>") < 0) // if there is only the <ref> tag, not the </ref> { mySection = "<ref>"; sstart = s.lastIndexOf(mySection); eend = sstart + 5; rreplacement = "*"; } else { var oneRef = ""; var counter = 0; if (mySection.indexOf("</ref>") > mySection.indexOf(oneRef)) { while (oneRef.indexOf("</ref>") < 0) { oneRef = oneRef + mySection.charAt(counter); ++counter; } } oneRef = oneRef + mySection.charAt(counter+1); oneRef = oneRef.split("<ref>")[1]; oneRef = oneRef.split("</ref>")[0]; sstart = s.lastIndexOf(mySection); eend = sstart + oneRef.length+11; rreplacement = "*" + oneRef; } b.push({start: sstart,end: eend,replacement: rreplacement, name: 'Invalid <ref></ref> tags',description: '<ref></ref> tags are located below the {{Reflist}} template, causing an error.' }); } }return b;});//***broken ref tags***ARA_Rules.push(function (s) {var b = []; var sstart; var eend; var rreplacement;if (s.indexOf("./ref>") > -1 || s.indexOf("</ref\n") > -1 || s.indexOf(",/ref>") > -1 || s.indexOf("</ref?") > -1) { if (s.indexOf("./ref>") > -1) { sstart = s.indexOf("./ref>"); eend = sstart + 6; rreplacement = "</ref>"; } else if (s.indexOf("</ref\n") > -1) { sstart = s.indexOf("</ref\n"); eend = sstart + 5; rreplacement = "</ref>"; } else if (s.indexOf("</ref?") > -1) { sstart = s.indexOf("</ref?"); eend = sstart + 6; rreplacement = "</ref>"; } else { sstart = s.indexOf(",/ref"); eend = sstart + 6; rreplacement = "</ref>"; } b.push({start: sstart,end: eend,replacement: rreplacement, name: 'broken <ref></ref> tags',description: 'Broken <ref> or </ref> tags exist on the page.'}); }return b;});//***broken reflist***ARA_Rules.push(function (s) {var b = []; var matches = [ { original: "{{reflist))", replacement: "{{Reflist}}" }, { original: "{{relist}}", replacement: "{{Reflist}}" }, { original: "{{reflist group", replacement: "{{Reflist|group"}, {original: "{{Reflist|2}\n",replacement: "{{Reflist|2}}\n"},{original: "{{Reflist||group=",replacement: "{{Reflist|group="}]; for (i = 0; i < matches.length; i++) { var match = matches[i]; if (s.includes(match.original)) { var startIndex = s.indexOf(match.original); b.push({start: startIndex,end: startIndex + match.original.length,replacement: match.replacement, name: "broken {{Reflist}}",description: "There is a broken Reflist template on the page"}); } }return b;});//***empty citations***ARA_Rules.push(function (s) {var b = []; var sstart; var eend; var rreplacement;if (s.indexOf("<ref></ref>") > -1) { var commentB = s.indexOf("<!--"); var commentE = s.indexOf("-->"); if (s.indexOf("<!--") < 0 || //to not break comments s.indexOf("<ref></ref>") < s.indexOf("<!--") || s.indexOf("<ref></ref>") > s.indexOf("-->") ) sstart = s.indexOf("<ref></ref>"); eend = sstart + 11; rreplacement = ""; b.push({start: sstart,end: eend,replacement: rreplacement, name: 'empty citations',description: 'Empty citations exist on the page.'}); }return b;});//***unnecessary whitespace in citation***ARA_Rules.push(function (s) {var b = []; var replaceableStrings = [" url = ", " url= ", "url =", "url= ", " url=", "group ="]; 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;});//***URL scheme error (Capital)***ARA_Rules.push(function (s) {var b = []; var matches = ["A", "B", "C", "D", "E", "F", "G", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]; for (i = 0; i < matches.length; i++){var match = "|url=" + matches[i];if (s.includes(match)){b.push({start: s.indexOf(match),end: s.indexOf(match) + 5,replacement: "|url=http://",name: 'URL scheme error (Capital)',description: 'Invalid URL parameter',sup1: 'prepend "http://"'});}}return b;});//***URL scheme error***ARA_Rules.push(function (s) {var b = []; var matches = ["a", "b", "c", "d", "e", "f", "g", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];for (i = 0; i < matches.length; i++){var match = "|url=" + matches[i];if (s.includes(match)){b.push({start: s.indexOf(match),end: s.indexOf(match) + 5,replacement: "|url=http://",name: 'URL scheme error',description: 'Invalid URL parameter'});}}return b;});//***space in URL parameter OR URL ends with period***ARA_Rules.push(function (s) {var b = []; //get indices of all '|url='s var startIndex = 0; var searchStr = "|url="; 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 |url={var urlStartIndex = indices[i] + searchStr.length;var indexOnward = s.substring(urlStartIndex); //+searchStr.length to exclude "|url="//get to the actual beginning of the URL if there are spaces or newlines after the "url=" and before the start of the urlwhile ((indexOnward[0] == ' ' || indexOnward[0] == '\n')){indexOnward = indexOnward.substring(1); //cut off the first character++urlStartIndex;}var fullRef = indexOnward;var fullRefPrevIndex = urlStartIndex - 1; //indices of various characters in the citationvar firstBracketAfterIndex = indexOnward.includes("}") ? indexOnward.indexOf("}") : s.length;var firstBarAfterIndex = indexOnward.includes("|") ? indexOnward.indexOf("|") : s.length;//get to the end of the citationfullRef = fullRef.substring(0, firstBracketAfterIndex);//get to the beginning of the citationwhile (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 URL parameter. The parameter should either end with another | or }} for the end of the ref (if not malformed)//find the nearest delimetervar cutOffIndex = firstBarAfterIndex;if (firstBracketAfterIndex < cutOffIndex) cutOffIndex = firstBracketAfterIndex;var url = indexOnward.substring(0, cutOffIndex).trim(); //the url parameter//if the url contains a spaceif (url.includes(" ")){//we will provide different options for the user, depending on which parameters are already included in the citation.//For example, if there is already a work or a website parameter, we don't want to suggest adding a 'work' parameter.//We will always suggest to replace the spaces with '%20' and to remove the content after the space in the URL.//If there are no 'work' or 'website' parameters, we will suggest a 'work' parameter.//If there are already 'work' or 'website' parameters and there isn't a 'publisher' param, we will suggest a 'publisher' parameter.//these don't changevar start1 = urlStartIndex;var end1 = urlStartIndex + url.length;var replacement1 = url.replace(new RegExp(" ", 'g'), "%20"); //replace all spaces in url with encoded spaces var supp1 = 'replace spaces with "%20"'; //note extra 'p' is intentionalvar startt3 = urlStartIndex + url.indexOf(" ");var endd3 = urlStartIndex + url.indexOf(" ") + url.substring(url.indexOf(" ")).length;var replacementt3 = "";var supp3 = 'remove content following url'; //note extra 'p' is intentional//if the citation doesn't already include 'work' or 'website' parametersif (!fullRef.includes("|work=") && !fullRef.includes("|website=")){b.push({start: start1,end: end1,replacement: replacement1, name: 'URL parameter containing space(s)',description: 'URLs cannot contain spaces',sup1: supp1,start2: urlStartIndex + url.indexOf(" "),end2: urlStartIndex + url.indexOf(" ") + 1, //+1 b/c we want to remove the space as wellreplacement2: "javascript:window.open('https://www.google.com/search?q=" + url + "', '_blank');",sup2: "Search Google for the current URL value",start3: startt3,end3: endd3,replacement3: replacementt3,sup3: supp3});}//otherwise, if the citation doesn't already include the 'publisher' parameterelse if (!fullRef.includes("|publisher=")){b.push({start: start1,end: end1,replacement: replacement1, name: 'URL parameter containing space(s)',description: 'URLs cannot contain spaces',sup1: supp1,start2: urlStartIndex + url.indexOf(" "),end2: urlStartIndex + url.indexOf(" ") + 1, //+1 b/c we want to remove the space as wellreplacement2: "|publisher=",sup2: 'split into "url" and "publisher"', //used for naming the 'sup' elementstart3: startt3,end3: endd3,replacement3: replacementt3,sup3: supp3});}//otherwise, the citation already contains a 'work' (or 'website') and 'publisher' params, so no 3rd optionelse{b.push({start: start1,end: end1,replacement: replacement1, name: 'URL parameter containing space(s)',description: 'URLs cannot contain spaces',sup1: supp1,start2: startt3,end2: endd3,replacement2: replacementt3,sup2: supp3});}}//alternatively, if the url ends with a periodelse if (url.endsWith('.')){b.push({start: urlStartIndex + url.length - 1,end: urlStartIndex + url.length,replacement: '', name: 'URL parameter ending with a period',description: 'URLs cannot end with periods',sup1: '[Remove trailing period]'});}}return b;});//***invalid ref position***ARA_Rules.push(function (s) {var b = []; var sstart; var eend; var rreplacement; var spacingType; var mySection;if (s.indexOf(" <ref") > -1 || s.indexOf("</ref>.") > -1 || s.indexOf("</ref>,") > -1) { if (s.indexOf(" <ref") > -1) { spacingType = " <ref"; sstart = s.indexOf(spacingType);eend = sstart + 5;rreplacement = "<ref"; } else if (s.indexOf("</ref>.") > -1) { var oneRef = "</ref>."; //oneRef = </ref>. var counter = s.indexOf(oneRef) - 1; while (oneRef.indexOf("<ref") < 0) { oneRef = s.charAt(counter) + oneRef; --counter; } //oneRef = <ref..>content</ref>. oneRef = oneRef.slice(0,oneRef.length-1); //oneRef = <ref..>content</ref> sstart = s.indexOf(oneRef); eend = sstart + oneRef.length + 1; rreplacement = "." + oneRef; } else if (s.indexOf("</ref>,") > -1) { var oneRef = "</ref>,"; //oneRef = </ref>, var counter = s.indexOf(oneRef) - 1; while (oneRef.indexOf("<ref") < 0) { oneRef = s.charAt(counter) + oneRef; --counter; } //oneRef = <ref..>content</ref>, oneRef = oneRef.slice(0,oneRef.length-1); //oneRef = <ref..>content</ref> sstart = s.indexOf(oneRef); eend = sstart + oneRef.length + 1; rreplacement = "," + oneRef; } b.push({start: sstart,end: eend,replacement: rreplacement, name: 'invalid ref position',description: 'invalid ref position.'}); }return b;});/*//***citation with accessdate and no URL***ARA_Rules.push(function (s) {var b = []; var sstart; var eend; var citation; var rreplacement; var restOfS;if (s.indexOf("{{cite") > -1) { citation = s.split("{{cite")[1]; citation = citation.split("}}")[0]; //move to next citation if the current one is fine if (citation.indexOf("accessdate") < 0 || citation.indexOf("url") > -1) { restOfS = s.slice(s.indexOf(citation)); restOfS = restOfS.slice(restOfS.indexOf("}}")); citation = restOfS.split("{{cite")[1]; citation = citation.split("}}")[0]; } //current citation has the problem else if (citation.indexOf("url") < 0 && citation.indexOf("accessdate") > -1) { var accessdateSection = "accessdate"; while (accessdateSection.indexOf("|") < 0 && accessdateSection.indexOf("{{") < 0 && accessdateSection.length < 30) { accessdateSection = citation.charAt(citation.indexOf(accessdateSection)-1) + accessdateSection; } // accessdateSection = "|" + accessdateSection; var theAccessdate = "accessdate"; while (theAccessdate.indexOf("|") < 0 && theAccessdate.indexOf("}}") < 0 && theAccessdate.length < 30) { theAccessdate = theAccessdate + citation.charAt(theAccessdate.length + 1); } sstart = s.indexOf(citation) + citation.indexOf(theAccessdate); //beginning of section: "|accessdate=" eend = sstart + theAccessdate.length;//- 10 + theAccessdate.length; //end of accessdate section (beginning of section - overlap + section b.push({start: sstart,end: eend,replacement: '', name: 'CS1 error: accessdate without URL',description: 'accessdate is listed in citation but URL is not' }); } } return b;});*///***References in Portals, per WP talk:Portal guidelines#References in portals***ARA_Rules.push(function (s) {var b = []; var sstart; var eend; var rreplacement; var name; if (document.URL.indexOf("title=Portal:") > -1 && s.indexOf("<ref") > -1) //page is a portal page that contains references { sstart = s.indexOf("<ref"); eend = s.indexOf("</ref>") + 6; //may possibly be overwritten below rreplacement = ""; //just take out the reference //if a reference has been previously named and the current reference is just a name, such as //<ref name="..." />, we'll need to handle this differently since the '/>' comes before another '</ref>' if (s.indexOf("<ref name") == s.indexOf("<ref")) //this is a named reference { var entireRef = s.substring(s.indexOf("<ref")); //get the supposed reference if (entireRef.indexOf("</ref>") > -1) //there is a closing ref tag on the page (possibly the closing tag to this ref) { entireRef = entireRef.substring(0,entireRef.indexOf("</ref>")); //cut at the the </ref> if (entireRef.indexOf("/>") > -1) //assume by this that the reference is an empty named reference eend = s.indexOf(entireRef) + entireRef.indexOf("/>") + 2; //stop at the "/>" } else //assume that the reference MUST be a named ref since there is no closing ref tag after this point eend = s.indexOf(entireRef) + entireRef.indexOf("/>") + 2; //stop at the "/>" } b.push({start: sstart,end: eend,replacement: rreplacement, name: 'references in Portal page',description: 'According to Portal guidelines, Portal pages should not contain references.'}); } return b;});//***Reflists in Portals, per WP talk:Portal guidelines#References in portals***ARA_Rules.push(function (s) {var b = []; var sstart; var eend; var rreplacement; var name; if (document.URL.indexOf("title=Portal:") > -1 && s.indexOf("{{Reflist}}") > -1) //page is a portal page that contains a Reflist { sstart = s.indexOf("{{Reflist}}"); eend = sstart + 11; rreplacement = ""; //just take out the reflist b.push({start: sstart,end: eend,replacement: rreplacement, name: '{{Reflist}} in Portal page',description: 'According to Portal guidelines, Portal pages should not contain {{Reflist}}s'}); } return b;});//***Empty Persondata template***ARA_Rules.push(function (s) {var b = []; var sstart; var eend; var rreplacement; var name; if (s.indexOf("{{Persondata}}") > -1) //blank persondata template { sstart = s.indexOf("{{Persondata}}"); eend = sstart + 14; rreplacement = "{{Persondata\n| NAME = \n| ALTERNATIVE NAMES = \n| SHORT DESCRIPTION = \n| DATE OF BIRTH = \n| PLACE OF BIRTH = \n| DATE OF DEATH = \n| PLACE OF DEATH = \n}}"; b.push({start: sstart,end: eend,replacement: rreplacement, name: 'empty Persondata template',description: 'The Persondata template missing required parameters.'}); } return b;});//***missing Name in Persondata***ARA_Rules.push(function (s) {var b = []; var sstart; var eend; var rreplacement; var name;if (s.indexOf("{{Persondata\n| NAME") > -1) //non-empty persondata template present { var afterName = s.substring(s.indexOf("{{Persondata\n| NAME")); afterName = afterName.substring(0, afterName.indexOf("}}")); //get just the persondata template var afterNameEq = afterName.indexOf("="); //first '=' in persondata is what we want afterName = afterName.substring(afterName.indexOf("| NAME")); afterName = afterName.substring(afterName.indexOf("NAME"), afterName.indexOf("\n")); //now we just have the NAME line if (afterName.indexOf("=") > -1) //contains the necessary equal sign { var afterEq = afterName.substring(afterName.indexOf("=") + 1); //get everything after the equals sign while (afterEq.length > 0 && afterEq.charAt(0) == ' ') //while beginning of string is whitespace afterEq = afterEq.substring(1); //remove whitespace if (afterEq == null || afterEq.length == 0) //no name is present { name = document.URL; if (name.indexOf("https") > -1) name = name.split("https:https://www.search.com.vn/wiki/index.php?lang=en&q=")[1]; else name = name.split("http:https://www.search.com.vn/wiki/index.php?lang=en&q=")[1]; name = name.split("&action=edit")[0]; while (name.indexOf("_") > -1) name = name.replace("_"," "); name = name.replace("&action=submit",""); String.prototype.countWords = function(){ return this.split(/\s+/).length;} if (name.indexOf("%C3%A1") > -1) name=name.replace("%C3%A1","á"); if (name.indexOf("%C4%87") > -1) name=name.replace("%C4%87","ć"); if (name.indexOf("%C5%82") > -1) name=name.replace("%C5%82","ł"); if (name.indexOf("%C3%B3")> -1) name=name.replace("%C3%B3","ó"); if (name.indexOf("%C5%9B") > -1) name=name.replace("%C5%9B","ś"); if (name.indexOf("%C3%BC") > -1) name=name.replace("%C3%BC","ü"); if (name.indexOf("%C5%BE") > -1) name=name.replace("%C5%BE","ž"); if (name.indexOf("%C5%A0") > -1) name=name.replace("%C5%A0","Š"); if (name.indexOf("%E2%80%93")>-1)name=name.replace("%E2%80%93","–"); if (name.indexOf("%27") > -1) name=name.replace("%27","'"); if (name.countWords() == 1 || name.indexOf(" of ") > -1 || name.indexOf(" the ") > -1) name = name; else if (name.countWords() == 2) { var firstName = name.split(" ")[0]; var lastName = name.split(" ")[1]; if (lastName.charAt(0) == "(") {var reversed = name;} else {var reversed = lastName.concat(", ").concat(firstName);} name = reversed; } else if (name.countWords() == 3) { var firstName = name.slice(0,name.indexOf(" ")); var midName = name.split(" ")[1]; var lastName = name.split(" ")[2]; if (midName == "of" || midName == "the") { var reversed = name;} else if (lastName.charAt(0) == "(") {var reversed = midName.concat(", ").concat(firstName).concat(" ").concat(lastName);} else {var reversed = lastName.concat(", ").concat(firstName).concat(" ").concat(midName);} name = reversed; } else if (name.countWords() == 4) { var firstName = name.slice(0,name.indexOf(" ")); var midName = name.split(" ")[1]; var lastName = name.split(" ")[2]; var name4 = name.split(" ")[3]; if (name4.charAt(name4.length-1) != ")") {var reversed = name4.concat(", ").concat(firstName).concat(" ").concat(midName).concat(" ").concat(lastName);} else {var reversed = midName.concat(", ").concat(firstName).concat(" ").concat(lastName).concat(" ").concat(name4);} name = reversed; } sstart = s.indexOf("{{Persondata\n| NAME") + afterNameEq; //location of '=' eend = sstart + 1; rreplacement = "= " + name; b.push({start: sstart,end: eend,replacement: rreplacement, name: 'missing Name in Persondata',description: 'The Persondata template is missing the \"Name\" parameter.'}); } } } return b;});} // end if mw.config.get('wgContentLanguage') === 'en'return ARA_Rules;}// </nowiki>
🔥 Top keywords: Main PageSpecial:SearchPage 3Wikipedia:Featured picturesHouse of the DragonUEFA Euro 2024Bryson DeChambeauJuneteenthInside Out 2Eid al-AdhaCleopatraDeaths in 2024Merrily We Roll Along (musical)Jonathan GroffJude Bellingham.xxx77th Tony AwardsBridgertonGary PlauchéKylian MbappéDaniel RadcliffeUEFA European Championship2024 ICC Men's T20 World CupUnit 731The Boys (TV series)Rory McIlroyN'Golo KantéUEFA Euro 2020YouTubeRomelu LukakuOpinion polling for the 2024 United Kingdom general electionThe Boys season 4Romania national football teamNicola CoughlanStereophonic (play)Gene WilderErin DarkeAntoine GriezmannProject 2025