Skip to content
Open
Changes from 7 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
08b3ac1
xfd: add "desired outcome" dropdown
NovemLinguae Apr 11, 2026
8997664
2 code review fixes
NovemLinguae Apr 12, 2026
3b16968
implement code review comment
NovemLinguae Apr 12, 2026
d012554
xfd: add more logic to AFD "Draftify" option
NovemLinguae Apr 12, 2026
f81844b
make list more compact, refactor nearby
NovemLinguae Apr 12, 2026
baf4aea
put back. will fix this in a separate patch
NovemLinguae Apr 13, 2026
ae4a9f3
xfd: add more logic to AFD "Redirect" option
NovemLinguae Apr 13, 2026
d4ca621
simplify reasonBox code, per code review
NovemLinguae Apr 16, 2026
f3055a4
refactor using jquery, and do element stuff after rendering
NovemLinguae Apr 16, 2026
80394a2
Merge branch 'master' into afd-merge-3
NovemLinguae Apr 16, 2026
f249bf2
rename target to afdtarget, to follow the pattern used by tfd/cfd
NovemLinguae Apr 16, 2026
e32b8fc
rename some more reason to afdreason. begin the "merging" logic.
NovemLinguae Apr 17, 2026
355fe80
add tests
NovemLinguae Apr 17, 2026
0621cf3
add tests
NovemLinguae Apr 17, 2026
031a206
add comment
NovemLinguae Apr 17, 2026
855d5df
add tagTargetPageWithMergeFromTag() to merging algorithm
NovemLinguae Apr 17, 2026
0f9025d
comments
NovemLinguae Apr 17, 2026
5e3c92a
remove {{Merge}}, {{Merge to}}, {{Merge from}}
NovemLinguae Apr 18, 2026
23075b8
add "to [[YOUR TARGET ARTICLE HERE]]" to default outcome
NovemLinguae Apr 18, 2026
c0f5002
make tagging the target page non-fatal. make warnings less verbose
NovemLinguae Apr 18, 2026
fa31a4c
implement 3 code review comments
NovemLinguae Apr 20, 2026
7223e03
implement 2 code review comments
NovemLinguae Apr 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 72 additions & 5 deletions src/modules/twinklexfd.js
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,19 @@ Twinkle.xfd.callback.change_category = function twinklexfdCallbackChangeCategory
style: 'margin-bottom: 5px; margin-top: -5px;'
});

work_area.append({
type: 'select',
name: 'outcome',
label: 'Desired outcome:',
event: Twinkle.xfd.callbacks.changeOutcome,
list: [
{ label: 'Delete', value: 'deletion' },
{ label: 'Merge', value: 'merging' },
{ label: 'Redirect', value: 'redirecting' },
{ label: 'Draftify', value: 'draftification' }
]
});

work_area.append({
type: 'checkbox',
list: [
Expand Down Expand Up @@ -750,6 +763,36 @@ Twinkle.xfd.callback.change_category = function twinklexfdCallbackChangeCategory
};

Twinkle.xfd.callbacks = {
changeOutcome: function(outcome) {
const form = outcome.target.form;
const reasonBox = form.querySelector('textarea[name="reason"]');
Comment thread
NovemLinguae marked this conversation as resolved.
Outdated
const targetInput = form.target;
if (outcome.target.value === 'redirecting') {
reasonBox.value = "I propose '''redirecting''' because ";
// add target text box
if (!targetInput) {
const targetElem = new Morebits.QuickForm.Element({
Comment thread
NovemLinguae marked this conversation as resolved.
Outdated
name: 'target',
type: 'input',
label: 'Target page:',
tooltip: 'Target page for the redirect.'
});
outcome.target.parentNode.appendChild(targetElem.render());
}
} else if (outcome.target.value === 'draftification') {
reasonBox.value = "I propose '''draftifying''' because ";
// remove target text box
if (targetInput) {
$(Morebits.QuickForm.getElementContainer(targetInput)).remove();
}
} else {
reasonBox.value = '';
// remove target text box
if (targetInput) {
$(Morebits.QuickForm.getElementContainer(targetInput)).remove();
}
}
},
// Requires having the tag text (params.tagText) set ahead of time
autoEditRequest: function(pageobj, params) {
const talkName = new mw.Title(pageobj.getPageName()).getTalkPage().toText();
Expand Down Expand Up @@ -900,11 +943,12 @@ Twinkle.xfd.callbacks = {
// Ensure items with User talk or no namespace prefix both end
// up at user talkspace as expected, but retain the
// prefix-less username for addToLog
notifyTarget = mw.Title.newFromText(notifyTarget, 3);
const userTalkNamespace = 3;
notifyTarget = mw.Title.newFromText(notifyTarget, userTalkNamespace);
const targetNS = notifyTarget.getNamespaceId();
const usernameOrTarget = notifyTarget.getRelativeText(3);
const usernameOrTarget = notifyTarget.getRelativeText(userTalkNamespace);
notifyTarget = notifyTarget.toText();
if (targetNS === 3) {
if (targetNS === userTalkNamespace) {
// Disallow warning yourself
if (usernameOrTarget === mw.config.get('wgUserName')) {
Morebits.Status.warn('You (' + usernameOrTarget + ') created this page; skipping user notification');
Expand All @@ -919,11 +963,18 @@ Twinkle.xfd.callbacks = {
actionName = actionName || 'Notifying initial contributor (' + usernameOrTarget + ')';
}

// For grep: Afd notice, Mfd notice, Tfd notice, Cfd notice, Ffd notice, Rfd notice
let notifytext = '\n{{subst:' + params.venue + ' notice';
// Venue-specific parameters
switch (params.venue) {
case 'afd':
notifytext += params.outcome !== 'deletion' ? '|outcome=' + params.outcome : '';
notifytext += params.target ? '|target=' + params.target : '';
// tell the template to add " (Xnd nomination)" to the XFD title, if needed
notifytext += params.numbering !== '' ? '|order= ' + params.numbering : '';
break;
case 'mfd':
// tell the template to add " (Xnd nomination)" to the XFD title, if needed
notifytext += params.numbering !== '' ? '|order= ' + params.numbering : '';
break;
case 'tfd':
Expand Down Expand Up @@ -1179,8 +1230,24 @@ Twinkle.xfd.callbacks = {
Twinkle.xfd.callbacks.addToLog(params, null);
}

params.tagText = (params.noinclude ? '<noinclude>{{' : '{{') + (params.number === '' ? 'subst:afd|help=off' : 'subst:afdx|' +
params.number + '|help=off') + (params.noinclude ? '}}</noinclude>\n' : '}}\n');
let noIncludeStart = '';
let noIncludeEnd = '';
if (params.noinclude) {
noIncludeStart = '<noinclude>';
noIncludeEnd = '</noinclude>';
}

let templateAndParams = '';
const outcome = params.outcome !== 'deletion' ? '|outcome=' + params.outcome : '';
const targetPage = params.target ? '|target=' + params.target : '';
const isFirstNomination = params.number === '';
if (isFirstNomination) {
templateAndParams = 'subst:afd|help=off' + outcome + targetPage;
} else {
templateAndParams = 'subst:afdx|' + params.number + '|help=off' + outcome + targetPage;
}

params.tagText = noIncludeStart + '{{' + templateAndParams + '}}' + noIncludeEnd + '\n';

if (pageobj.canEdit()) {
// Remove some tags that should always be removed on AfD.
Expand Down
Loading