diff --git a/.eslintrc.json b/.eslintrc.json
index 5f5867080..4d69942fb 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -56,13 +56,9 @@
"no-new": "warn",
"no-return-assign": "warn",
"no-script-url": "warn",
- "no-throw-literal": "warn",
- "no-underscore-dangle": "warn",
"no-unused-expressions": "warn",
"no-use-before-define": "warn",
- "no-useless-concat": "warn",
"no-var": "warn",
- "prefer-const": "warn",
"unicorn/prefer-string-slice": "warn"
}
}
diff --git a/DEVELOPER.md b/DEVELOPER.md
index cfc3334ab..08e1883e0 100644
--- a/DEVELOPER.md
+++ b/DEVELOPER.md
@@ -180,3 +180,14 @@ All the dependencies that Twinkle uses are JavaScript **dev** dependencies. They
- mwn - Used when you run `npm start`. `npm start` is what enables localhost testing.
When updating dependencies, CI should take care of testing most of that. Manually testing `npm start` should be the only additional check needed.
+
+### Adding a CSD
+
+Here is a checklist for writing a patch to add a speedy deletion criteria called A1:
+
+* Write a patch similar to this one: https://github.com/wikimedia-gadgets/twinkle/pull/2097/files
+* If you want any of the config options to be on by default (instead of off by default), modify twinkle.js -> Twinkle.defaultConfig.
+* On wiki, create these pages. Copy an existing template and adjust as needed.
+ * Template:Db-a1, which will be placed on the page tagged for deletion.
+ * Template:Db-a1-notice, which will be placed on the user talk page of the author of the page tagged for deletion.
+ * Template:Db-a1-deleted, which will be placed on the user talk page of the author of the page deleted.
diff --git a/modules/twinklearv.js b/modules/twinklearv.js
index a115db0b5..81019b349 100644
--- a/modules/twinklearv.js
+++ b/modules/twinklearv.js
@@ -306,7 +306,7 @@ Twinkle.arv.callback.changeCategory = function (e) {
work_area.append(
{
type: 'dyninput',
- name: 'sockpuppet',
+ name: 'sockpuppets',
label: 'Sockpuppets',
sublabel: 'Sock:',
tooltip: 'The username of the sockpuppet without the "User:" prefix',
@@ -574,26 +574,32 @@ Twinkle.arv.callback.evaluate = function(e) {
case 'sock':
/* falls through */
case 'puppet':
- var sockParameters = {
- evidence: form.evidence.value.trim(),
- checkuser: form.checkuser.checked
- };
+ var reportData = Twinkle.arv.callback.getSpiReportData(input);
- var puppetReport = form.category.value === 'puppet';
- if (puppetReport && !form.sockmaster.value.trim()) {
- alert('You have not entered a sockmaster account for this puppet. Consider reporting this account as a sockpuppeteer instead.');
- return;
- } else if (!puppetReport && !form.sockpuppet[0].value.trim()) {
- alert('You have not entered any sockpuppet account(s) for this sockmaster. Consider reporting this account as a sockpuppet instead.');
+ if (reportData.error) {
+ alert(reportData.error);
return;
}
- sockParameters.uid = puppetReport ? form.sockmaster.value.trim() : uid;
- sockParameters.sockpuppets = puppetReport ? [uid] : Morebits.array.uniq($.map($('input:text[name=sockpuppet]', form), (o) => $(o).val() || null));
-
Morebits.SimpleWindow.setButtonsEnabled(false);
Morebits.Status.init(form);
- Twinkle.arv.processSock(sockParameters);
+
+ Morebits.wiki.addCheckpoint(); // prevent notification events from causing an erronous "action completed"
+
+ var reportpage = 'Wikipedia:Sockpuppet investigations/' + reportData.sockmaster;
+
+ Morebits.wiki.actionCompleted.redirect = reportpage;
+ Morebits.wiki.actionCompleted.notice = 'Reporting complete';
+
+ var spiPage = new Morebits.wiki.page(reportpage, 'Retrieving discussion page');
+ spiPage.setFollowRedirect(true);
+ spiPage.setEditSummary('Adding new report for [[Special:Contributions/' + reportData.sockmaster + '|' + reportData.sockmaster + ']].');
+ spiPage.setChangeTags(Twinkle.changeTags);
+ spiPage.setAppendText(reportData.wikitext);
+ spiPage.setWatchlist(Twinkle.getPref('spiWatchReport'));
+ spiPage.append();
+
+ Morebits.wiki.removeCheckpoint(); // all page updates have been started
break;
case 'an3':
@@ -818,32 +824,34 @@ Twinkle.arv.callback.getUsernameReportWikitext = function(input) {
return text;
};
-Twinkle.arv.processSock = function(params) {
- Morebits.wiki.addCheckpoint(); // prevent notification events from causing an erronous "action completed"
+Twinkle.arv.callback.getSpiReportData = function(input) {
+ const isPuppetReport = input.category === 'puppet';
- // prepare the SPI report
- let text = '\n{{subst:SPI report|' +
- params.sockpuppets.map((sock, index) => (index + 1) + '=' + sock).join('|') + '\n|evidence=' + params.evidence + ' \n';
+ if (!isPuppetReport) {
+ input.sockpuppets = input.sockpuppets.filter((sock) => sock !== ''); // ignore empty sockpuppet inputs
+ }
- if (params.checkuser) {
- text += '|checkuser=yes';
+ if (isPuppetReport && !input.sockmaster) {
+ return { error: 'You have not entered a sockmaster account for this puppet. Consider reporting this account as a sockpuppeteer instead.' };
+ } else if (!isPuppetReport && input.sockpuppets.length === 0) {
+ return { error: 'You have not entered any sockpuppet account(s) for this sockmaster. Consider reporting this account as a sockpuppet instead.' };
}
- text += '}}';
- const reportpage = 'Wikipedia:Sockpuppet investigations/' + params.uid;
+ input.sockmaster = input.sockmaster || input.uid;
+ input.sockpuppets = isPuppetReport ? [input.uid] : Morebits.array.uniq(input.sockpuppets);
- Morebits.wiki.actionCompleted.redirect = reportpage;
- Morebits.wiki.actionCompleted.notice = 'Reporting complete';
+ let text = '\n{{subst:SPI report|' +
+ input.sockpuppets.map((sock, index) => (index + 1) + '=' + sock).join('|') + '\n|evidence=' + input.evidence + ' \n';
- const spiPage = new Morebits.wiki.Page(reportpage, 'Retrieving discussion page');
- spiPage.setFollowRedirect(true);
- spiPage.setEditSummary('Adding new report for [[Special:Contributions/' + params.uid + '|' + params.uid + ']].');
- spiPage.setChangeTags(Twinkle.changeTags);
- spiPage.setAppendText(text);
- spiPage.setWatchlist(Twinkle.getPref('spiWatchReport'));
- spiPage.append();
+ if (input.checkuser) {
+ text += '|checkuser=yes';
+ }
+ text += '}}';
- Morebits.wiki.removeCheckpoint(); // all page updates have been started
+ return {
+ sockmaster: input.sockmaster,
+ wikitext: text
+ };
};
Twinkle.arv.processAN3 = function(params) {
@@ -921,19 +929,19 @@ Twinkle.arv.processAN3 = function(params) {
ret += sub.reverse().map((v) => (sub.length >= 2 ? '#' : '') + '# {{diff2|' + v.revid + '|' + new Morebits.Date(v.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC)}} ' + hasHiddenComment(v)).join('\n');
return ret;
}).reverse().join('\n');
- const warningtext = params.warnings.reverse().map((v) => '# ' + ' {{diff2|' + v.revid + '|' + new Morebits.Date(v.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC)}} ' + hasHiddenComment(v)).join('\n');
- let resolvetext = params.resolves.reverse().map((v) => '# ' + ' {{diff2|' + v.revid + '|' + new Morebits.Date(v.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC)}} ' + hasHiddenComment(v)).join('\n');
+ const warningtext = params.warnings.reverse().map((v) => '# {{diff2|' + v.revid + '|' + new Morebits.Date(v.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC)}} ' + hasHiddenComment(v)).join('\n');
+ let resolvetext = params.resolves.reverse().map((v) => '# {{diff2|' + v.revid + '|' + new Morebits.Date(v.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC)}} ' + hasHiddenComment(v)).join('\n');
if (params.free_resolves) {
const page = params.free_resolves;
if (page.compare) {
- resolvetext += '\n# ' + ' {{diff|oldid=' + page.compare.fromrevid + '|diff=' + page.compare.torevid + '|label=Consecutive edits on ' + page.compare.totitle + '}}';
+ resolvetext += '\n# {{diff|oldid=' + page.compare.fromrevid + '|diff=' + page.compare.torevid + '|label=Consecutive edits on ' + page.compare.totitle + '}}';
} else if (page.revisions) {
const revCount = page.revisions.length;
let rev;
if (revCount < 3) { // diff=prev or next
rev = revCount === 1 ? page.revisions[0] : page.revisions[1];
- resolvetext += '\n# ' + ' {{diff2|' + rev.revid + '|' + new Morebits.Date(rev.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC) on ' + page.title + '}} ' + hasHiddenComment(rev);
+ resolvetext += '\n# {{diff2|' + rev.revid + '|' + new Morebits.Date(rev.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC) on ' + page.title + '}} ' + hasHiddenComment(rev);
} else { // diff and oldid are nonconsecutive
rev = page.revisions[0];
const revLatest = page.revisions[revCount - 1];
@@ -949,7 +957,7 @@ Twinkle.arv.processAN3 = function(params) {
comment += ' ~~~~';
}
- const text = '\n\n' + '{{subst:AN3 report|diffs=' + difftext + '|warnings=' + warningtext + '|resolves=' + resolvetext + '|pagename=' + params.page + '|orig=' + origtext + '|comment=' + comment + '|uid=' + params.uid + '}}';
+ const text = '\n\n{{subst:AN3 report|diffs=' + difftext + '|warnings=' + warningtext + '|resolves=' + resolvetext + '|pagename=' + params.page + '|orig=' + origtext + '|comment=' + comment + '|uid=' + params.uid + '}}';
const reportpage = 'Wikipedia:Administrators\' noticeboard/Edit warring';
diff --git a/modules/twinklebatchdelete.js b/modules/twinklebatchdelete.js
index 257c6097c..11a4b0940 100644
--- a/modules/twinklebatchdelete.js
+++ b/modules/twinklebatchdelete.js
@@ -277,9 +277,9 @@ Twinkle.batchdelete.callback.toggleSubpages = function twDbatchToggleSubpages(e)
if (subpagesLoaded) {
$.each(Twinkle.batchdelete.pages, (i, el) => {
- // Get back the subgroup from subgroup_, where we saved it
- if (el.subgroup === null && el.subgroup_) {
- el.subgroup = el.subgroup_;
+ // Get back the subgroup from subgroupBeforeDeletion, where we saved it
+ if (el.subgroup === null && el.subgroupBeforeDeletion) {
+ el.subgroup = el.subgroupBeforeDeletion;
}
});
@@ -388,10 +388,10 @@ Twinkle.batchdelete.callback.toggleSubpages = function twDbatchToggleSubpages(e)
$.each(Twinkle.batchdelete.pages, (i, el) => {
if (el.subgroup) {
- // Remove subgroup after saving its contents in subgroup_
+ // Remove subgroup after saving its contents in subgroupBeforeDeletion
// so that it can be retrieved easily if user decides to
// delete the subpages again
- el.subgroup_ = el.subgroup;
+ el.subgroupBeforeDeletion = el.subgroup;
el.subgroup = null;
}
});
diff --git a/modules/twinklebatchprotect.js b/modules/twinklebatchprotect.js
index 6f745f26d..8e7c61486 100644
--- a/modules/twinklebatchprotect.js
+++ b/modules/twinklebatchprotect.js
@@ -180,7 +180,8 @@ Twinkle.batchprotect.callback = function twinklebatchprotectCallback() {
pages.sort(Twinkle.sortByNamespace);
pages.forEach((page) => {
const metadata = [];
- let missing = !!page.missing, editProt;
+ const missing = !!page.missing;
+ let editProt;
if (missing) {
metadata.push('page does not exist');
diff --git a/modules/twinkleblock.js b/modules/twinkleblock.js
index 16c39050c..f4342aa1c 100644
--- a/modules/twinkleblock.js
+++ b/modules/twinkleblock.js
@@ -2,7 +2,8 @@
(function() {
-let api = new mw.Api(), relevantUserName, blockedUserName;
+const api = new mw.Api();
+let relevantUserName, blockedUserName;
const menuFormattedNamespaces = $.extend({}, mw.config.get('wgFormattedNamespaces'));
menuFormattedNamespaces[0] = '(Article)';
@@ -156,8 +157,8 @@ Twinkle.block.fetchedData = {};
// Processes the data from a a query response, separated from
// Twinkle.block.fetchUserInfo to allow reprocessing of already-fetched data
Twinkle.block.processUserInfo = function twinkleblockProcessUserInfo(data, fn) {
- let blockinfo = data.query.blocks[0],
- userinfo = data.query.users[0];
+ let blockinfo = data.query.blocks[0];
+ const userinfo = data.query.users[0];
// If an IP is blocked *and* rangeblocked, the above finds
// whichever block is more recent, not necessarily correct.
// Three seems... unlikely
@@ -296,7 +297,8 @@ Twinkle.block.callback.change_block64 = function twinkleblockCallbackChangeBlock
};
Twinkle.block.callback.change_action = function twinkleblockCallbackChangeAction(e) {
- let field_preset, field_template_options, field_block_options, $form = $(e.target.form);
+ let field_preset, field_template_options, field_block_options;
+ const $form = $(e.target.form);
// Make ifs shorter
const blockBox = $form.find('[name=actiontype][value=block]').is(':checked');
const templateBox = $form.find('[name=actiontype][value=template]').is(':checked');
@@ -1534,7 +1536,7 @@ Twinkle.block.callback.change_expiry = function twinkleblockCallbackChangeExpiry
Twinkle.block.seeAlsos = [];
Twinkle.block.callback.toggle_see_alsos = function twinkleblockCallbackToggleSeeAlso() {
const reason = this.form.reason.value.replace(
- new RegExp('( )?'), ''
+ new RegExp('( )?'), ''
);
Twinkle.block.seeAlsos = Twinkle.block.seeAlsos.filter((el) => el !== this.value);
@@ -1572,7 +1574,8 @@ Twinkle.block.callback.toggle_ds_reason = function twinkleblockCallbackToggleDSR
};
Twinkle.block.callback.update_form = function twinkleblockCallbackUpdateForm(e, data) {
- let form = e.target.form, expiry = data.expiry;
+ const form = e.target.form;
+ let expiry = data.expiry;
// don't override original expiry if useInitialOptions is set
if (!data.useInitialOptions) {
@@ -1723,11 +1726,11 @@ Twinkle.block.callback.preview = function twinkleblockcallbackPreview(form) {
};
Twinkle.block.callback.evaluate = function twinkleblockCallbackEvaluate(e) {
- let $form = $(e.target),
+ const $form = $(e.target),
toBlock = $form.find('[name=actiontype][value=block]').is(':checked'),
toWarn = $form.find('[name=actiontype][value=template]').is(':checked'),
- toPartial = $form.find('[name=actiontype][value=partial]').is(':checked'),
- blockoptions = {}, templateoptions = {};
+ toPartial = $form.find('[name=actiontype][value=partial]').is(':checked');
+ let blockoptions = {}, templateoptions = {};
Twinkle.block.callback.saveFieldset($form.find('[name=field_block_options]'));
Twinkle.block.callback.saveFieldset($form.find('[name=field_template_options]'));
@@ -1899,13 +1902,14 @@ Twinkle.block.callback.issue_template = function twinkleblockCallbackIssueTempla
// "talk page" of an IP range (which does not exist)
const userTalkPage = 'User_talk:' + mw.config.get('wgRelevantUserName');
- const params = $.extend(formData, {
- messageData: Twinkle.block.blockPresetsInfo[formData.template],
- reason: Twinkle.block.field_template_options.block_reason,
- disabletalk: Twinkle.block.field_template_options.notalk,
- noemail: Twinkle.block.field_template_options.noemail_template,
- nocreate: Twinkle.block.field_template_options.nocreate_template
- });
+ const params = Twinkle.block.combineFormDataAndFieldTemplateOptions(
+ formData,
+ Twinkle.block.blockPresetsInfo[formData.template],
+ Twinkle.block.field_template_options.block_reason,
+ Twinkle.block.field_template_options.notalk,
+ Twinkle.block.field_template_options.noemail_template,
+ Twinkle.block.field_template_options.nocreate_template
+ );
Morebits.wiki.actionCompleted.redirect = userTalkPage;
Morebits.wiki.actionCompleted.notice = 'Actions complete, loading user talk page in a few seconds';
@@ -1915,8 +1919,19 @@ Twinkle.block.callback.issue_template = function twinkleblockCallbackIssueTempla
wikipedia_page.load(Twinkle.block.callback.main);
};
+Twinkle.block.combineFormDataAndFieldTemplateOptions = function(formData, messageData, reason, disabletalk, noemail, nocreate) {
+ return $.extend(formData, {
+ messageData: messageData,
+ reason: reason,
+ disabletalk: disabletalk,
+ noemail: noemail,
+ nocreate: nocreate
+ });
+};
+
Twinkle.block.callback.getBlockNoticeWikitext = function(params) {
- let text = '{{', settings = Twinkle.block.blockPresetsInfo[params.template];
+ let text = '{{';
+ const settings = Twinkle.block.blockPresetsInfo[params.template];
if (!settings.nonstandard) {
text += 'subst:' + params.template;
if (params.article && settings.pageParam) {
@@ -1990,10 +2005,10 @@ Twinkle.block.callback.getBlockNoticeWikitext = function(params) {
};
Twinkle.block.callback.main = function twinkleblockcallbackMain(pageobj) {
- let params = pageobj.getCallbackParameters(),
+ const params = pageobj.getCallbackParameters(),
date = new Morebits.Date(pageobj.getLoadTime()),
- messageData = params.messageData,
- text;
+ messageData = params.messageData;
+ let text;
params.indefinite = Morebits.string.isInfinity(params.expiry);
@@ -2003,7 +2018,8 @@ Twinkle.block.callback.main = function twinkleblockcallbackMain(pageobj) {
} else {
text = pageobj.getPageText();
- let dateHeaderRegex = date.monthHeaderRegex(), dateHeaderRegexLast, dateHeaderRegexResult;
+ const dateHeaderRegex = date.monthHeaderRegex();
+ let dateHeaderRegexLast, dateHeaderRegexResult;
while ((dateHeaderRegexLast = dateHeaderRegex.exec(text)) !== null) {
dateHeaderRegexResult = dateHeaderRegexLast;
}
diff --git a/modules/twinkleconfig.js b/modules/twinkleconfig.js
index 6e11c3fb4..c88e74ebf 100644
--- a/modules/twinkleconfig.js
+++ b/modules/twinkleconfig.js
@@ -10,10 +10,6 @@
and adds an ad box to the top of user subpages belonging to the
currently logged-in user which end in '.js'
* Active on: What I just said. Yeah.
-
- I, [[User:This, that and the other]], originally wrote this. If the code is misbehaving, or you have any
- questions, don't hesitate to ask me. (This doesn't at all imply [[WP:OWN]]ership - it's just meant to
- point you in the right direction.) -- TTO
*/
Twinkle.config = {};
@@ -1075,7 +1071,8 @@ Twinkle.config.init = function twinkleconfigInit() {
}
cell = document.createElement('td');
- let label, input, gotPref = Twinkle.getPref(pref.name);
+ let label, input;
+ const gotPref = Twinkle.getPref(pref.name);
switch (pref.type) {
case 'boolean': // create a checkbox
@@ -1295,9 +1292,11 @@ Twinkle.config.init = function twinkleconfigInit() {
// Styled in twinkle.css
box.setAttribute('id', 'twinkle-config-headerbox');
- let link,
- scriptPageName = mw.config.get('wgPageName').slice(mw.config.get('wgPageName').lastIndexOf('/') + 1,
- mw.config.get('wgPageName').lastIndexOf('.js'));
+ let link;
+ const scriptPageName = mw.config.get('wgPageName').slice(
+ mw.config.get('wgPageName').lastIndexOf('/') + 1,
+ mw.config.get('wgPageName').lastIndexOf('.js')
+ );
if (scriptPageName === 'twinkleoptions') {
// place "why not try the preference panel" notice
@@ -1694,6 +1693,7 @@ Twinkle.config.writePrefs = function twinkleconfigWritePrefs(pageobj) {
'// changing the configuration parameters in a valid-JavaScript way) will be\n' +
'// overwritten the next time you click "save" in the Twinkle preferences\n' +
'// panel. If modifying this file, make sure to use correct JavaScript.\n' +
+ // eslint-disable-next-line no-useless-concat
'// \n' +
'\n' +
'window.Twinkle.prefs = ';
@@ -1701,6 +1701,7 @@ Twinkle.config.writePrefs = function twinkleconfigWritePrefs(pageobj) {
text +=
';\n' +
'\n' +
+ // eslint-disable-next-line no-useless-concat
'// \n' +
'// End of twinkleoptions.js\n';
diff --git a/modules/twinkleprotect.js b/modules/twinkleprotect.js
index e34bb0a8c..3bc6ada64 100644
--- a/modules/twinkleprotect.js
+++ b/modules/twinkleprotect.js
@@ -173,7 +173,8 @@ Twinkle.protect.fetchProtectionLevel = function twinkleprotectFetchProtectionLev
const pageid = protectData[0].query.pageids[0];
const page = protectData[0].query.pages[pageid];
- let current = {}, adminEditDeferred;
+ const current = {};
+ let adminEditDeferred;
// Save requested page's watched status for later in case needed when filing request
Twinkle.protect.watched = page.watchlistexpiry || page.watched === '';
diff --git a/modules/twinklerollback.js b/modules/twinklerollback.js
index d7a276082..747022784 100644
--- a/modules/twinklerollback.js
+++ b/modules/twinklerollback.js
@@ -280,7 +280,7 @@ Twinkle.rollback.addLinks = {
const warnFromTalk = function(xtitle) {
const $talkLink = $('#mw-diff-' + xtitle + '2 .mw-usertoollinks a').first();
if ($talkLink.length) {
- let extraParams = 'vanarticle=' + mw.util.rawurlencode(Morebits.pageNameNorm) + '&' + 'noautowarn=true';
+ let extraParams = 'vanarticle=' + mw.util.rawurlencode(Morebits.pageNameNorm) + '&noautowarn=true';
// diffIDs for vanarticlerevid
extraParams += '&vanarticlerevid=';
extraParams += xtitle === 'otitle' ? mw.config.get('wgDiffOldId') : mw.config.get('wgDiffNewId');
diff --git a/modules/twinklespeedy.js b/modules/twinklespeedy.js
index 1d2a681b1..308f894a8 100644
--- a/modules/twinklespeedy.js
+++ b/modules/twinklespeedy.js
@@ -39,9 +39,8 @@ Twinkle.speedy.hasCSD = !!$('#delete-reason').length;
// Prepares the speedy deletion dialog and displays it
Twinkle.speedy.initDialog = function twinklespeedyInitDialog(callbackfunc) {
- let dialog;
Twinkle.speedy.dialog = new Morebits.SimpleWindow(Twinkle.getPref('speedyWindowWidth'), Twinkle.getPref('speedyWindowHeight'));
- dialog = Twinkle.speedy.dialog;
+ const dialog = Twinkle.speedy.dialog;
dialog.setTitle('Choose criteria for speedy deletion');
dialog.setScriptName('Twinkle');
dialog.addFooterLink('Speedy deletion policy', 'WP:CSD');
@@ -1140,8 +1139,8 @@ Twinkle.speedy.callbacks = {
}
if (initialContrib) {
- let usertalkpage = new Morebits.wiki.Page('User talk:' + initialContrib, 'Notifying initial contributor (' + initialContrib + ')'),
- notifytext, i, editsummary;
+ const usertalkpage = new Morebits.wiki.Page('User talk:' + initialContrib, 'Notifying initial contributor (' + initialContrib + ')');
+ let notifytext, i, editsummary;
// special cases: "db" and "db-multiple"
if (params.normalizeds.length > 1) {
@@ -1221,7 +1220,7 @@ Twinkle.speedy.callbacks = {
if (reason === null) {
return Morebits.Status.error('Asking for reason', 'User cancelled');
} else if (!reason || !reason.replace(/^\s*/, '').replace(/\s*$/, '')) {
- return Morebits.Status.error('Asking for reason', "you didn't give one. I don't know... what with admins and their apathetic antics... I give up...");
+ return Morebits.Status.error('Asking for reason', 'The "reason" for deleting was not provided, or Twinkle was unable to compute it. Aborting.');
}
const deleteMain = function(callback) {
@@ -1367,8 +1366,8 @@ Twinkle.speedy.callbacks = {
// given the params, builds the template and also adds the user talk page parameters to the params that were passed in
// returns => [ wikitext,