Open main menu
Home
Random
Donate
Recent changes
Special pages
Community portal
Preferences
About Stockhub
Disclaimers
Search
User menu
Talk
Contributions
Create account
Log in
Editing
Module:Speedy
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
local getArgs = require("Module:Arguments").getArgs local pageType = require("Module:Pagetype") local mbox = require("Module:Message box") local yesno = require("Module:Yesno") local button = require('Module:Clickable button 2') local preview = require('Module:If preview') local p = {} local config = mw.loadData('Module:Speedy/config') local timeAgo = require('Module:Time ago') ---------------------------------------------------------------------------- -- message function from [[Module:Documentation]] ---------------------------------------------------------------------------- local fillStringWithArgs local function message(cfgKey, valArray, expectType) --[[ -- Gets a message from the cfg table and formats it if appropriate. -- The function raises an error if the value from the cfg table is not -- of the type expectType. The default type for expectType is 'string'. -- If the table valArray is present, strings such as $1, $2 etc. in the -- message are substituted with values from the table keys [1], [2] etc. -- For example, if the message "foo-message" had the value 'Foo $2 bar $1.', -- message('foo-message', {'baz', 'qux'}) would return "Foo qux bar baz." --]] local msg = config.messages[cfgKey] expectType = expectType or 'string' if type(msg) ~= expectType then error('message: type error in message cfg.' .. cfgKey .. ' (' .. expectType .. ' expected, got ' .. type(msg) .. ')', 2) end if not valArray then return msg end return fillStringWithArgs(msg, valArray) end function fillStringWithArgs(text, valArray) if not valArray then return text end local function getVal(match) match = tonumber(match) return valArray[match] or '' end return mw.ustring.gsub(text, '$([1-9][0-9]*)', getVal) .. '' end local function detectParameters(text) return text and mw.ustring.find(text, '$([1-9][0-9]*)') and true or false end local function makeUnorderedList(array) local ul = mw.html.create('ul') for k,v in pairs(array) do local li = ul:tag('li') li:wikitext(v) li:done() end ul:allDone() return tostring(ul) end local function makeWikiList(array) local out = '' for k,v in pairs(array) do out = out .. '* ' .. v .. '\n' end return out end ---------------------------------------------------------------------------- -- Argument processing (from [[Module:Documentation]]) ---------------------------------------------------------------------------- local function makeInvokeFunc(funcName) return function (frame) local args = getArgs(frame, { valueFunc = function (key, value) if type(value) == 'string' then value = value:match('^%s*(.-)%s*$') -- Remove whitespace. if key == 'heading' or value ~= '' then return value else return nil end else return value end end }) return p[funcName](args) end end ---------------------------------------------------------------------------- -- Miscellaneous functions related to speedy deletion ---------------------------------------------------------------------------- local function getDeletionEntry(code) return config.deletionCodes[code] end local function yn(input, default) local res = yesno(input, nil) if (res == nil) then return default else return res end end local function processDeletionArgs(iparams) local args = { deletionReasons = {}, deletionReasonsNotice = {}, entries = {}, numberOfEntries = 0, hideButton = true, highestMessage = 0, drv = false, willProvide = false, hide = false, blank = false } local entry = nil local replaceParams = false local params = {iparams.page or mw.title.getCurrentTitle().fullText} local paramNo = 2 local skipped = true local function cleanupLeftover(v) if entry then table.insert(args.deletionReasons, '<span style="font-style:normal;">' .. fillStringWithArgs(entry.description, params) .. '.</span> ' .. (entry.more and '<span style="font-weight:normal;"> ' .. entry.more .. '</span> ' or '') .. '<span style="font-style:normal;">' .. message('deleteIntroCriteriaLink', {entry.code}) .. '.</span>') table.insert(args.deletionReasonsNotice, fillStringWithArgs(entry.description, params) .. ' ([[WP:CSD#' .. entry.code .. '|CSD ' .. entry.code .. ']]). ' .. (entry.additionalMessage and fillStringWithArgs(entry.additionalMessage, params) or '')) table.insert(args.entries, entry) else if (v ~= '') then table.insert(args.deletionReasons, v) table.insert(args.deletionReasonsNotice, v) end table.insert(args.entries, {}) end params = {iparams.page or mw.title.getCurrentTitle().fullText} paramNo = 2 args.customHeader = entry and ((entry.notice or 2) >= args.highestMessage) and entry.customHeader or args.customHeader args.customIntro = entry and ((entry.notice or 2) >= args.highestMessage) and entry.customIntro or args.customIntroDeleted args.customIntroDeleted = entry and ((entry.notice or 2) >= args.highestMessage) and entry.customIntroDeleted or args.customIntroDeleted args.customCloser = entry and ((entry.notice or 2) >= args.highestMessage) and entry.customCloser or args.customCloser args.numberOfEntries = args.numberOfEntries + 1 args.hideButton = entry and (args.hideButton and (entry.notice or 2) == 0) or false args.highestMessage = entry and ((entry.notice or 2) >= args.highestMessage) and entry.notice or args.highestMessage args.drv = entry and (args.drv or entry.drv) or args.drv args.willProvide = entry and entry.willProvide or args.willProvide args.hide = entry and (entry.hide or args.hide) or args.hide args.blank = entry and (entry.blank or args.blank) or args.blank end for k,v in ipairs(iparams) do if type(k) == type(1) then skipped = false if (replaceParams) then local pName = fillStringWithArgs(entry and entry.inputFormat[paramNo - 1] or '$2', {iparams.page or mw.title.getCurrentTitle().fullText, v}) paramNo = paramNo + 1 table.insert(params, pName) else entry = getDeletionEntry(v) or nil replaceParams = entry and detectParameters(entry.description) or false end if not replaceParams then cleanupLeftover(v) end end end if replaceParams then cleanupLeftover('') end if skipped then args.hideButton = false end args.help = yn(iparams.help, true) args.nocat = yn(iparams.nocat, false) args.bot = yn(iparams.bot, false) args.noHeader = yn(iparams.noheader, false) args.additionalNote = iparams.additionalnote args.pageName = iparams.page args.notice = yn(iparams.notice, false) args.date = iparams.date or mw.getCurrentFrame():preprocess('{{safesubst:REVISIONTIMESTAMP}}') return args end local function isSubstituted() return yn(mw.getCurrentFrame():preprocess('{{safesubst:Issubst}}')) end ---------------------------------------------------------------------------- -- Entry point ---------------------------------------------------------------------------- p.main = makeInvokeFunc('_main') function p._main(params) -- get page local args = processDeletionArgs(params) local out = '' if args.notice then if not args.pageName then return preview._warning({'No page name specified. Proceeding will do nothing.'}) end if not args.noHeader then out = out .. (args.customHeader and '== ' .. fillStringWithArgs(args.customHeader, {args.pageName}) .. ' ==' or "== " .. message("noticeHeader", {args.pageName}) .. " ==") .. '\n' end local messageType = args.highestMessage == 1 and 'welcome' or 'notice' out = out .. (message('level' .. args.highestMessage .. 'icon') == '' and '' or '[[' .. message('level' .. args.highestMessage .. 'icon') .. '|40px]] ') if mw.title.new(args.pageName).exists then if args.customIntro then out = out .. fillStringWithArgs(args.customIntro, { args.pageName, args.deletionReasonsNotice[1] }) .. '\n\n' elseif args.numberOfEntries == 1 then out = out .. message(messageType .. 'Message', { args.pageName, args.deletionReasonsNotice[1] }) .. '\n\n' elseif args.numberOfEntries > 1 then out = out .. message(messageType .. 'MessageMultiple', { args.pageName, '\n' .. makeWikiList(args.deletionReasonsNotice) }) .. '\n' else out = out .. message(messageType .. 'MessageMultiple', { args.pageName, message("seePageForWhy") }) .. '\n\n' end if args.customCloser then out = out .. args.customCloser else out = out .. '{{#ifexist:' .. args.pageName .. '|' if args.hideButton then out = out .. message("removeSpeedyMessage", {args.pageName}) .. ' ' else out = out .. message("contestMessage", {args.pageName, '{{button|' .. message("contestButton") .. '}}'}) .. ' ' out = out .. message('closingWarning', {message('removeSpeedyWarning')}) .. ' ' end if args.willProvide then out = out .. message('undeleteSuggestion', {message('pageIsDeleted'), args.pageName, message(args.drv and 'requestDeletionReview' or 'requestUndeletion')}) end out = out .. '|' out = out .. message('deletedAfterMessage') .. ' ' if not args.hideButton then out = out .. message('closingWarning', {message('recreateWarning')}) .. ' ' end if args.willProvide then out = out .. message('undeleteSuggestion', {message('pageShouldNotHaveBeenDeleted'), args.pageName, message(args.drv and 'requestDeletionReview' or 'requestUndeletion')}) end out = out .. '}}' end else if args.customIntroDeleted then out = out .. fillStringWithArgs(args.customIntroDeleted, { args.pageName, args.deletionReasonsNotice[1] }) .. '\n\n' elseif args.numberOfEntries == 1 then out = out .. message(messageType .. 'MessageDeleted', { args.pageName, args.deletionReasonsNotice[1] }) .. '\n\n' elseif args.numberOfEntries > 1 then out = out .. message(messageType .. 'MessageDeletedMultiple', { args.pageName, '\n' .. makeWikiList(args.deletionReasonsNotice) }) .. '\n\n' else out = out .. message(messageType .. 'MessageDeletedMultiple', { args.pageName, message("seePageForWhy") }) .. '\n\n' end if args.customCloser then out = out .. args.customCloser else out = out .. message('deletedAfterMessage') if not args.hideButton then out = out .. message('closingWarning', {message('recreateWarning')}) .. ' ' end if args.willProvide then out = out .. message('undeleteSuggestion', {message('pageShouldNotHaveBeenDeleted'), args.pageName, message(args.drv and 'requestDeletionReview' or 'requestUndeletion')}) end end end return mw.getCurrentFrame():preprocess(out) else if isSubstituted() then local out = '{{db/sandbox' for k,v in ipairs(params) do out = out .. '|' .. v end out = out .. (args.help and '' or '|help=off') out = out .. (args.nocat and '|nocat=yes' or '') out = out .. (args.bot and '|bot=yes' or '') out = out .. (args.additionalNote and '|additionalnote=' .. args.additionalNote or '') out = out .. (args.date and '|date=' .. args.date or '{{safesubst:REVISIONTIMESTAMP}}') out = out .. '}}' return out else local titleOfPage = mw.title.getCurrentTitle() local pt = pageType._main({page = titleOfPage.fullText}) local introPrefixToUse = args.bot and 'bot' or 'delete' local intro = mw.html.create('span') intro:css{["font-style"] = "italic", ["font-weight"] = "bold"} if args.numberOfEntries == 1 then intro:wikitext(message(introPrefixToUse .. 'Intro', { pt, args.deletionReasons[1] })) elseif args.numberOfEntries > 1 then intro:wikitext(message(introPrefixToUse .. 'IntroMultiple', { pt, makeUnorderedList(args.deletionReasons) })) else intro:wikitext(message(introPrefixToUse .. 'IntroMultiple', { pt, message("noReasonWarning") })) end intro:allDone() out = out .. tostring(intro) if args.additionalNote then out = out .. ' ' .. message('additionalNote', { args.additionalNote }) end out = out .. '\n' if args.hideButton then out = out .. '' .. message("removeNoticeNoButton", {pt}) .. '' else out = out .. '' .. message("removeNotice", {pt, message('removeNoticeWarning', {titleOfPage.isTalkPage and message('checkBelow') or '[[' .. titleOfPage.talkPageTitle.fullText .. '|' .. message('visitTheTalkPage') .. ']]'})}) .. '' out = out .. '\n\n' if args.numberOfEntries == 1 then out = out .. '<div style="margin-left:auto;margin-right:auto;text-align:center;">' .. button.luaMain({ message("contestButton"), class="mw-ui-progressive", url="{{fullurl:" .. titleOfPage.talkPageTitle.fullText .. '|action=edit§ion=new&preloadtitle={{urlencode:' .. message('contestPreloadTitle') .. '}}&preload={{urlencode:' .. (mw.title.new(message('contestPreload', {args.entries[1].code})).exists and message('contestPreload', {args.entries[1].code}) or message('contestPreloadGeneric')) .. '}}&editintro={{urlencode:' .. message('contestPreloadEditintro') .. '}}}}' }) .. '</div>' else out = out .. '<div style="margin-left:auto;margin-right:auto;text-align:center;">' .. button.luaMain({ message("contestButton"), class="mw-ui-progressive", style="text-align:center;", url="{{fullurl:" .. titleOfPage.talkPageTitle.fullText .. '|action=edit§ion=new&preload={{urlencode:' .. message('contestPreloadGeneric') .. '}}&editintro={{urlencode:' .. message('contestPreloadEditintro') .. '}}}}' }) .. '</div>' end out = out .. '\n\n' out = out .. '' .. message("deleteCloser", { pt, titleOfPage.isTalkPage and message("deleteCloserProvidedBelowNotice") or message("deleteCloserProvidedOnTalkPage") }) .. "" if (args.help) then out = out .. '\n\n' local templateCall = '<code><nowiki>{{subst:db|page=' .. titleOfPage.fullText for k,v in pairs(params) do templateCall = templateCall .. '|' .. k .. '=' .. v end templateCall = templateCall .. '|notice=yes}} ~~' .. '~~</nowiki></code>' out = out .. '' .. message('deleteNoticeTemplate', {templateCall}) .. '' end out = out .. '\n\n' if titleOfPage.talkPageTitle.exists then out = out .. '<span class="sysop-show">' .. message("hangOnAdmin", {pt, titleOfPage.isTalkPage and message("checkBelow") or message("hangOnTalkPage")}) .. "</span> " else out = out .. message('hangOn', {pt}) end end if args.numberOfEntries == 1 then out = out .. (args.entries[1].notes and '\n\n' .. args.entries[1].notes .. "" or '') end local deleteReasonSummary = '' if args.numberOfEntries > 1 then deleteReasonSummary = 'Multiple criteria: ' local isFirst = true for k,v in pairs(args.entries) do deleteReasonSummary = v.code and deleteReasonSummary .. (isFirst and '' or ', ') .. '[[WP:CSD#' .. v.code .. '|' .. v.code .. ']]' or '' isFirst = false end elseif args.numberOfEntries == 1 then deleteReasonSummary = args.entries[1].code and deleteReasonSummary .. '[[WP:CSD#' .. args.entries[1].code .. '|' .. args.entries[1].code .. ']]' or '' end if deleteReasonSummary == '' then deleteReasonSummary = '[[WP:CSD|Speedy]]' end out = out .. '\n\n' local lastEditUser = mw.getCurrentFrame():callParserFunction('REVISIONUSER', titleOfPage.fullText) local editDate = mw.getCurrentFrame():callParserFunction('#time', 'H:i, j F Y', mw.getCurrentFrame():callParserFunction('REVISIONTIMESTAMP', titleOfPage.fullText)) out = out .. '<span class="sysop-show">' .. message(args.bot and 'checkBot' or 'check', {args.bot and message('check', {deleteReasonSummary}) or deleteReasonSummary}) .. '</span> ' .. message('lastEdited', { '[[User:' .. lastEditUser .. '|' .. lastEditUser .. ']]', '<span class="plainlinks">[{{fullurl:' .. titleOfPage.fullText .. '|action=history}} ' .. editDate .. ']</span>', timeAgo.main({editDate}) }) -- categorize out = out .. '[[' .. (args.nocat and ':' or '') .. 'Category:' .. message('defaultCategory') .. ']]' for k,v in pairs(args.entries) do local categorizeTime = mw.getCurrentFrame():preprocess('{{#time:U|' .. args.date .. ' +' .. (v and v.delayCategorization or 0) .. ' days' .. '}}') local currentTime = mw.getCurrentFrame():preprocess('{{#time:U|now}}') if currentTime + 0 >= categorizeTime + 0 then for l,w in pairs(v and v.categories or {}) do out = out .. '[[' .. (args.nocat and ':' or '') .. 'Category:' .. w .. ']]' end end end local deletionBoxArgs = { type = "speedy", text = mw.getCurrentFrame():preprocess(out), style = "font-size:95%;word-break:break-word;", image = message('level' .. args.highestMessage .. 'icon') == '' and 'none' or '[[' .. message('level' .. args.highestMessage .. 'icon') .. '|40px]]' } local deletionBox = mbox.main('mbox', deletionBoxArgs) local blankedBox = '' local hiddenBox = '' local blanked = '' local hidden = '' if args.blank then blanked = blanked .. message('blanked') if mw.getCurrentFrame():preprocess('{{REVISIONSIZE}}') + 0 >= 35 then blanked = blanked .. ' <b>' .. message('pleaseBlank') .. '</b>' end local blankedBoxArgs = { type = "notice", text = blanked, style = "word-break:break-word;" } blankedBox = mbox.main('mbox', blankedBoxArgs) end if args.hide then hidden = hidden .. message('hidden') local hiddenBoxArgs = { type = "notice", text = hidden, style = "word-break:break-word;" } hiddenBox = mbox.main('mbox', hiddenBoxArgs) end if args.hide and not args.nocat then hiddenBox = hiddenBox .. '<div style="display:none">' end return deletionBox .. blankedBox .. hiddenBox end end end p.makeTable = makeInvokeFunc('_makeTable') function p._makeTable(args) local usedCodes = {} local tb = mw.html.create("table") tb:addClass('wikitable') local th = tb:tag('tr') th:tag('th'):wikitext('Code'):done() th:tag('th'):wikitext('Aliases'):done() th:tag('th'):wikitext('Criterion'):done() th:tag('th'):wikitext('Name'):done() th:tag('th'):wikitext('Description'):done() for k,v in pairs(config.deletionReasonsSorting) do local entry = getDeletionEntry(v) if entry then if not usedCodes[v] then local tr = tb:tag('tr') tr:tag('td'):wikitext(mw.getCurrentFrame():preprocess('<code><nowiki>' .. v .. '</nowiki></code>')):done() local aliasStr = '' for _,alias in pairs(entry.aliases) do aliasStr = aliasStr .. '<code><nowiki>' .. alias .. '</nowiki></code>' usedCodes[alias] = true end tr:tag('td'):wikitext(mw.getCurrentFrame():preprocess(aliasStr)) tr:tag('td'):wikitext('[[Project:CSD#' .. entry.code .. '|' .. entry.code .. ']]'):done() tr:tag('td'):wikitext(entry.name):done() tr:tag('td'):wikitext(entry.description):done() usedCodes[v] = true end end end for k,entry in pairs(config.deletionCodes) do if not usedCodes[k] then local tr = tb:tag('tr') tr:tag('td'):wikitext(mw.getCurrentFrame():preprocess('<code><nowiki>' .. k .. '</nowiki></code>')):done() local aliasStr = '' for _,alias in pairs(entry.aliases) do aliasStr = aliasStr .. '<code><nowiki>' .. alias .. '</nowiki></code>' usedCodes[alias] = true end tr:tag('td'):wikitext(mw.getCurrentFrame():preprocess(aliasStr)) tr:tag('td'):wikitext('[[Project:CSD#' .. entry.code .. '|' .. entry.code .. ']]'):done() tr:tag('td'):wikitext(entry.name):done() tr:tag('td'):wikitext(entry.description):done() usedCodes[k] = true end end return tostring(tb) .. '' end p.makeTableWithExamples = makeInvokeFunc('_makeTableWithExamples') function p._makeTableWithExamples(args) local usedCodes = {} local tb = mw.html.create("table") tb:addClass('wikitable') local th = tb:tag('tr') th:tag('th'):css{position = "sticky", top = 0, left = 0}:wikitext('Codes'):done() --th:tag('th'):wikitext('Criterion'):done() th:tag('th'):css{position = "sticky", top = 0}:wikitext('Deletion message'):done() th:tag('th'):css{position = "sticky", top = 0}:wikitext('Deletion notice'):done() for k,v in pairs(config.deletionReasonsSorting) do local entry = getDeletionEntry(v) if entry then if not usedCodes[v] then local tr = tb:tag('tr') local aliasStr = '' for _,alias in pairs(entry.aliases) do aliasStr = aliasStr .. '<br/><code><nowiki>{{db|' .. alias .. '}}</nowiki></code>' usedCodes[alias] = true end tr:tag('td'):css{position = "sticky", left = 0}:wikitext(mw.getCurrentFrame():preprocess('<code><nowiki>{{db|' .. v .. '}}</nowiki></code>' .. aliasStr)):done() --tr:tag('td'):wikitext('[[Project:CSD#' .. entry.code .. '|' .. entry.code .. ']]'):done() tr:tag('td'):wikitext('<div style="width:700px;">' .. mw.getCurrentFrame():preprocess('{{#invoke:Speedy|main|nocat=yes|' .. v .. '}}' .. '</div>' )):done() tr:tag('td'):wikitext(mw.getCurrentFrame():preprocess('<div style="width:700px;">' .. '{{#invoke:Speedy|main|page=Sandbox|notice=yes|' .. v .. '}}' .. '</div>')):done() usedCodes[v] = true end end end for v,entry in pairs(config.deletionCodes) do if not usedCodes[v] then local tr = tb:tag('tr') local aliasStr = '' for _,alias in pairs(entry.aliases) do aliasStr = aliasStr .. '<br/><code><nowiki>{{db|' .. alias .. '}}</nowiki></code>' usedCodes[alias] = true end tr:tag('td'):css{position = "sticky", left = 0}:wikitext(mw.getCurrentFrame():preprocess('<code><nowiki>{{db|' .. v .. '}}</nowiki></code>\n' .. aliasStr)):done() --tr:tag('td'):wikitext('[[Project:CSD#' .. entry.code .. '|' .. entry.code .. ']]'):done() tr:tag('td'):wikitext('<div style="width:700px;">' .. mw.getCurrentFrame():preprocess('{{#invoke:Speedy|main|nocat=yes|' .. v .. '}}' .. '</div>' )):done() tr:tag('td'):wikitext(mw.getCurrentFrame():preprocess('<div style="width:700px;">' .. '{{#invoke:Speedy|main|page=Sandbox|notice=yes|' .. v .. '}}' .. '</div>')):done() usedCodes[v] = true end end return tostring(tb) .. '' end return p
Summary:
Please note that all contributions to Stockhub may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
Stockhub:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Templates used on this page:
Template:Module other
(
edit
)
Template:Module rating
(
edit
)
Template:Ombox
(
edit
)
Template:Sandbox other
(
edit
)
Module:Arguments
(
edit
)
Module:Clickable button 2
(
edit
)
Module:If preview
(
edit
)
Module:If preview/configuration
(
edit
)
Module:If preview/styles.css
(
edit
)
Module:Message box
(
edit
)
Module:Message box/configuration
(
edit
)
Module:Message box/ombox.css
(
edit
)
Module:Namespace detect
(
edit
)
Module:Namespace detect/config
(
edit
)
Module:Namespace detect/data
(
edit
)
Module:Pagetype
(
edit
)
Module:Pagetype/config
(
edit
)
Module:Speedy
(
edit
)
Module:Speedy/config
(
edit
)
Module:Speedy/doc
(
edit
)
Module:String
(
edit
)
Module:Time ago
(
edit
)
Module:Yesno
(
edit
)