Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

speedy/xfd: Handle non-wikitext contentmodels #1208

Merged
merged 3 commits into from
Dec 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
171 changes: 99 additions & 72 deletions modules/twinklespeedy.js
Original file line number Diff line number Diff line change
Expand Up @@ -1438,99 +1438,126 @@ Twinkle.speedy.callbacks = {
return;
}

var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();

statelem.status('Checking for tags on the page...');

// check for existing deletion tags
var tag = /(?:\{\{\s*(db|delete|db-.*?|speedy deletion-.*?)(?:\s*\||\s*\}\}))/.exec(text);
// This won't make use of the db-multiple template but it probably should
if (tag && !confirm('The page already has the CSD-related template {{' + tag[1] + '}} on it. Do you want to add another CSD template?')) {
return;
}

var xfd = /\{\{((?:article for deletion|proposed deletion|prod blp|template for discussion)\/dated|[cfm]fd\b)/i.exec(text) || /#invoke:(RfD)/.exec(text);
if (xfd && !confirm('The deletion-related template {{' + xfd[1] + '}} was found on the page. Do you still want to add a CSD template?')) {
return;
}

// given the params, builds the template and also adds the user talk page parameters to the params that were passed in
// returns => [<string> wikitext, <object> utparams]
var buildData = Twinkle.speedy.callbacks.getTemplateCodeAndParams(params),
code = buildData[0];
params.utparams = buildData[1];

// curate/patrol the page
if (Twinkle.getPref('markSpeedyPagesAsPatrolled')) {
pageobj.triage();
// Set the correct value for |ts= parameter in {{db-g13}}
if (params.normalizeds.indexOf('g13') !== -1) {
code = code.replace('$TIMESTAMP', pageobj.getLastEditTime());
}

// Wrap SD template in noinclude tags if we are in template space.
// Won't work with userboxes in userspace, or any other transcluded page outside template space
if (mw.config.get('wgNamespaceNumber') === 10) { // Template:
code = '<noinclude>' + code + '</noinclude>';
}
// Tag if possible, post on talk if not
if (pageobj.canEdit() && ['wikitext', 'Scribunto', 'javascript', 'css', 'sanitized-css'].indexOf(pageobj.getContentModel()) !== -1) {
var text = pageobj.getPageText();

// Remove tags that become superfluous with this action
text = text.replace(/\{\{\s*([Uu]serspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/g, '');
if (mw.config.get('wgNamespaceNumber') === 6) {
// remove "move to Commons" tag - deletion-tagged files cannot be moved to Commons
text = text.replace(/\{\{(mtc|(copy |move )?to ?commons|move to wikimedia commons|copy to wikimedia commons)[^}]*\}\}/gi, '');
}
statelem.status('Checking for tags on the page...');

if (params.requestsalt) {
if (params.normalizeds.indexOf('g10') === -1) {
code += '\n{{salt}}';
} else {
code = '{{salt}}\n' + code;
// check for existing deletion tags
var tag = /(?:\{\{\s*(db|delete|db-.*?|speedy deletion-.*?)(?:\s*\||\s*\}\}))/.exec(text);
// This won't make use of the db-multiple template but it probably should
if (tag && !confirm('The page already has the CSD-related template {{' + tag[1] + '}} on it. Do you want to add another CSD template?')) {
return;
}
}

// Scribunto isn't parsed like wikitext, so CSD templates on modules need special handling to work
if (mw.config.get('wgPageContentModel') === 'Scribunto') {
var equals = '';
while (code.indexOf(']' + equals + ']') !== -1) {
equals += '=';
var xfd = /\{\{((?:article for deletion|proposed deletion|prod blp|template for discussion)\/dated|[cfm]fd\b)/i.exec(text) || /#invoke:(RfD)/.exec(text);
if (xfd && !confirm('The deletion-related template {{' + xfd[1] + '}} was found on the page. Do you still want to add a CSD template?')) {
return;
}
code = "require('Module:Module wikitext')._addText([" + equals + '[' + code + ']' + equals + ']);';
}

// Generate edit summary for edit
var editsummary;
if (params.normalizeds.length > 1) {
editsummary = 'Requesting speedy deletion (';
$.each(params.normalizeds, function(index, norm) {
editsummary += '[[WP:CSD#' + norm.toUpperCase() + '|CSD ' + norm.toUpperCase() + ']], ';
});
editsummary = editsummary.substr(0, editsummary.length - 2); // remove trailing comma
editsummary += ').';
} else if (params.normalizeds[0] === 'db') {
editsummary = 'Requesting [[WP:CSD|speedy deletion]] with rationale "' + params.templateParams[0]['1'] + '".';
} else {
editsummary = 'Requesting speedy deletion ([[WP:CSD#' + params.normalizeds[0].toUpperCase() + '|CSD ' + params.normalizeds[0].toUpperCase() + ']]).';
}
// curate/patrol the page
if (Twinkle.getPref('markSpeedyPagesAsPatrolled')) {
pageobj.triage();
}

// Set the correct value for |ts= parameter in {{db-g13}}
if (params.normalizeds.indexOf('g13') !== -1) {
code = code.replace('$TIMESTAMP', pageobj.getLastEditTime());
}
// Wrap SD template in noinclude tags if we are in template space.
// Won't work with userboxes in userspace, or any other transcluded page outside template space
if (mw.config.get('wgNamespaceNumber') === 10) { // Template:
code = '<noinclude>' + code + '</noinclude>';
}

// Remove tags that become superfluous with this action
text = text.replace(/\{\{\s*([Uu]serspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/g, '');
if (mw.config.get('wgNamespaceNumber') === 6) {
// remove "move to Commons" tag - deletion-tagged files cannot be moved to Commons
text = text.replace(/\{\{(mtc|(copy |move )?to ?commons|move to wikimedia commons|copy to wikimedia commons)[^}]*\}\}/gi, '');
}

// Blank attack pages
if (params.normalizeds.indexOf('g10') !== -1) {
text = code;
} else {
// Insert tag after short description or any hatnotes
var wikipage = new Morebits.wikitext.page(text);
text = wikipage.insertAfterTemplates(code + '\n', Twinkle.hatnoteRegex).getText();
}
if (params.requestsalt) {
if (params.normalizeds.indexOf('g10') === -1) {
code += '\n{{salt}}';
} else {
code = '{{salt}}\n' + code;
}
}

if (mw.config.get('wgPageContentModel') === 'Scribunto') {
// Scribunto isn't parsed like wikitext, so CSD templates on modules need special handling to work
var equals = '';
while (code.indexOf(']' + equals + ']') !== -1) {
equals += '=';
}
code = "require('Module:Module wikitext')._addText([" + equals + '[' + code + ']' + equals + ']);';
} else if (['javascript', 'css', 'sanitized-css'].indexOf(mw.config.get('wgPageContentModel')) !== -1) {
// Likewise for JS/CSS pages
code = '/* ' + code + ' */';
}

// Generate edit summary for edit
var editsummary;
if (params.normalizeds.length > 1) {
editsummary = 'Requesting speedy deletion (';
$.each(params.normalizeds, function(index, norm) {
editsummary += '[[WP:CSD#' + norm.toUpperCase() + '|CSD ' + norm.toUpperCase() + ']], ';
});
editsummary = editsummary.substr(0, editsummary.length - 2); // remove trailing comma
editsummary += ').';
} else if (params.normalizeds[0] === 'db') {
editsummary = 'Requesting [[WP:CSD|speedy deletion]] with rationale "' + params.templateParams[0]['1'] + '".';
} else {
editsummary = 'Requesting speedy deletion ([[WP:CSD#' + params.normalizeds[0].toUpperCase() + '|CSD ' + params.normalizeds[0].toUpperCase() + ']]).';
}

// Blank attack pages
if (params.normalizeds.indexOf('g10') !== -1) {
text = code;
} else {
// Insert tag after short description or any hatnotes
var wikipage = new Morebits.wikitext.page(text);
text = wikipage.insertAfterTemplates(code + '\n', Twinkle.hatnoteRegex).getText();
}

pageobj.setPageText(text);
pageobj.setEditSummary(editsummary);
pageobj.setWatchlist(params.watch);
pageobj.save(Twinkle.speedy.callbacks.user.tagComplete);

pageobj.setPageText(text);
pageobj.setEditSummary(editsummary);
pageobj.setWatchlist(params.watch);
pageobj.save(Twinkle.speedy.callbacks.user.tagComplete);
} else { // Attempt to place on talk page
var talkName = new mw.Title(pageobj.getPageName()).getTalkPage().toText();
if (talkName !== pageobj.getPageName()) {
if (params.requestsalt) {
code += '\n{{salt}}';
}

pageobj.getStatusElement().warn('Unable to edit page, placing tag on talk page');

var talk_page = new Morebits.wiki.page(talkName, 'Automatically placing tag on talk page');
talk_page.setNewSectionTitle(pageobj.getPageName() + ' nominated for CSD, request deletion');
talk_page.setNewSectionText(code + '\n\nI was unable to tag ' + pageobj.getPageName() + ' so please delete it. ~~~~');
talk_page.setCreateOption('recreate');
talk_page.setFollowRedirect(true);
talk_page.setWatchlist(params.watch);
talk_page.setChangeTags(Twinkle.changeTags);
talk_page.setCallbackParameters(params);
talk_page.newSection(Twinkle.speedy.callbacks.user.tagComplete);
} else {
pageobj.getStatusElement().error('Page protected and nowhere to add an edit request, aborting');
}
}
},

tagComplete: function(pageobj) {
Expand Down
47 changes: 34 additions & 13 deletions modules/twinklexfd.js
Original file line number Diff line number Diff line change
Expand Up @@ -1314,12 +1314,19 @@ Twinkle.xfd.callbacks = {
taggingTemplate: function(pageobj) {
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
var tableNewline = params.templatetype === 'standard' || params.templatetype === 'sidebar' ? '\n' : ''; // No newline for inline

params.tagText = (params.noinclude ? '<noinclude>' : '') + '{{subst:template for discussion|help=off' +
(params.templatetype !== 'standard' ? '|type=' + params.templatetype : '') + (params.noinclude ? '}}</noinclude>' : '}}') + tableNewline;
params.tagText = '{{subst:template for discussion|help=off' + (params.templatetype !== 'standard' ? '|type=' + params.templatetype : '') + '}}';

if (pageobj.canEdit()) {
if (pageobj.getContentModel() === 'sanitized-css') {
params.tagText = '/* ' + params.tagText + ' */';
} else {
if (params.noinclude) {
params.tagText = '<noinclude>' + params.tagText + '</noinclude>';
}
params.tagText += params.templatetype === 'standard' || params.templatetype === 'sidebar' ? '\n' : ''; // No newline for inline
}

if (pageobj.canEdit() && ['wikitext', 'sanitized-css'].indexOf(pageobj.getContentModel()) !== -1) {
Copy link
Collaborator Author

@Amorymeltzer Amorymeltzer Nov 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These three make use of the autoEditRequest from #1091, but it means that the language is currently saying that the page was protected, which is wrong. Is it excessive to create a new template just for this? We could do a separate if (and function?) like is done for twinklespeedy.js in this PR and not rely on that functionality. Alternatively, adding a parameter to the function could allow for a bespoke message, but it's not currently easy to detect protection status, so a less good option overall.

pageobj.setPageText(params.tagText + text);
pageobj.setEditSummary('Nominated for deletion; see [[:' + params.discussionpage + ']].');
pageobj.setChangeTags(Twinkle.changeTags);
Expand All @@ -1335,13 +1342,20 @@ Twinkle.xfd.callbacks = {
taggingTemplateForMerge: function(pageobj) {
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();
var tableNewline = params.templatetype === 'standard' || params.templatetype === 'sidebar' ? '\n' : ''; // No newline for inline

params.tagText = (params.noinclude ? '<noinclude>' : '') + '{{subst:tfm|help=off|' +
(params.templatetype !== 'standard' ? 'type=' + params.templatetype + '|' : '') + '1=' + params.otherTemplateName.replace(/^(?:Template|Module):/, '') +
(params.noinclude ? '}}</noinclude>' : '}}') + tableNewline;
params.tagText = '{{subst:tfm|help=off|' + (params.templatetype !== 'standard' ? 'type=' + params.templatetype + '|' : '') +
'1=' + params.otherTemplateName.replace(/^(?:Template|Module):/, '') + '}}';

if (pageobj.canEdit()) {
if (pageobj.getContentModel() === 'sanitized-css') {
params.tagText = '/* ' + params.tagText + ' */';
} else {
if (params.noinclude) {
params.tagText = '<noinclude>' + params.tagText + '</noinclude>';
}
params.tagText += params.templatetype === 'standard' || params.templatetype === 'sidebar' ? '\n' : ''; // No newline for inline
}

if (pageobj.canEdit() && ['wikitext', 'sanitized-css'].indexOf(pageobj.getContentModel()) !== -1) {
pageobj.setPageText(params.tagText + text);
pageobj.setEditSummary('Listed for merging with [[:' + params.otherTemplateName + ']]; see [[:' + params.discussionpage + ']].');
pageobj.setChangeTags(Twinkle.changeTags);
Expand Down Expand Up @@ -1461,11 +1475,18 @@ Twinkle.xfd.callbacks = {
var text = pageobj.getPageText();
var params = pageobj.getCallbackParameters();

params.tagText = (params.noinclude ? '<noinclude>' : '') + '{{' +
(params.number === '' ? 'mfd' : 'mfdx|' + params.number) + '|help=off}}\n' +
(params.noinclude ? '</noinclude>' : '');
params.tagText = '{{' + (params.number === '' ? 'mfd' : 'mfdx|' + params.number) + '|help=off}}';

if (pageobj.canEdit()) {
if (['javascript', 'css', 'sanitized-css'].indexOf(mw.config.get('wgPageContentModel')) !== -1) {
params.tagText = '/* ' + params.tagText + ' */\n';
} else {
params.tagText += '\n';
if (params.noinclude) {
params.tagText = '<noinclude>' + params.tagText + '</noinclude>';
}
}

if (pageobj.canEdit() && ['wikitext', 'javascript', 'css', 'sanitized-css'].indexOf(pageobj.getContentModel()) !== -1) {
pageobj.setPageText(params.tagText + text);
pageobj.setEditSummary('Nominated for deletion; see [[:' + params.discussionpage + ']].');
pageobj.setChangeTags(Twinkle.changeTags);
Expand Down