Module:Article history/config
From Thetacola Wiki
< Module:Article history
Jump to navigationJump to search
Revision as of 12:04, 3 June 2022 by en>Izno (remove small)
File:Full-protection-shackle.svg | This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
File:Lua-Logo.svg | This module depends on the following other modules: |
This module holds configuration for Module:Article history. For instructions on how to edit it, see the comments in the code, and see Module:Article history#Class documentation for how to use the different objects.
------------------------------------------------------------------------------- -- Configuration data for [[Module:Article history]] ------------------------------------------------------------------------------- local lang = mw.language.getContentLanguage() local Category = require('Module:Article history/Category') ------------------------------------------------------------------------------- -- Helper functions ------------------------------------------------------------------------------- -- Makes a link to a template page surrounded by double curly braces. A -- workalike for the {{tl}} template. local function makeTemplateLink(s) local openb = mw.text.nowiki('{{') local closeb = mw.text.nowiki('}}') return string.format('%s[[Template:%s|%s]]%s', openb, s, s, closeb) end -- Gets the Good Article topic for the given key. Uses -- [[Module:Good article topics]]. local function getGoodArticleTopic(key) if not key then return nil end return require('Module:Good article topics')._main(key) end -- Returns the Good Article page link and display value for a given Good Article -- key. If the key wasn't valid, the default Good Article page and display value -- is returned instead. local function getGoodArticleTopicLink(key) local topic = getGoodArticleTopic(key) local link, display if topic then link = 'Wikipedia:Good articles/' .. topic display = topic .. ' good articles' else link = 'Wikipedia:Good articles' display = 'good articles' end return link, display end -- Wrapper function for mw.language:formatDate, going through pcall to catch -- invalid input errors. local function getDate(format, date) local success, result = pcall(lang.formatDate, lang, format, date) if success then return result end end -- Gets the date in the format YYYYMMDD, as a number. Months and dates are -- zero-padded. Results from this function are intended to be used in date -- calculations. local function getYmdDate(date) date = getDate('Ymd', date) if date then return tonumber(date) else return nil end end -- Gets the date in the format Month d, YYYY. local function getLongDate(date) return getDate('F j, Y', date) end -- Returns true if the given page is an existing title, and false or nil -- otherwise local function titleExists(page) local success, title = pcall(mw.title.new, page) return success and title.exists end -- Returns a truthy value if a date parameter for the given prefix has been -- provided by the user. local function isActiveDatedObject(articleHistoryObj, prefix) local args = articleHistoryObj.args local prefixArgs = articleHistoryObj.prefixArgs return args[prefix .. 'date'] or prefixArgs[prefix] end -- Returns a date as formatted by getLongDate. If the date is invalid, it raises -- an error using param as the parameter name containing the invalid date. local function validateDate(param, date, articleHistoryObj) local longDate = getLongDate(date) if longDate then return longDate else articleHistoryObj:raiseError( string.format( "invalid date '%s' detected in parameter '%s'", tostring(date), param ), 'Template:Article history#Invalid date' ) end end -- Generates a data table for a date-related notice such as DYK and ITN. prefix -- is the parameter prefix for that notice type (e.g. "dyk"), and suffixes is -- an array of parameter suffixes in addition to "date" that is used by that -- notice type (e.g. "entry" for the "dykentry" and "dyk2entry" parameters). local function makeDateData(articleHistoryObj, prefix, suffixes) local args = articleHistoryObj.args local prefixArgs = articleHistoryObj.prefixArgs -- Sanity checks if prefixArgs[prefix] then for _, t in ipairs(prefixArgs[prefix]) do if not t.date then articleHistoryObj:raiseError( string.format( "an argument starting with '%s%d' was detected, " .. "but no '%s%ddate' parameter was specified", prefix, t[1], prefix, t[1] ), 'Template:Article history#No date parameter' ) end end end local data = {} -- Organise the input local function addData(sep) local t = {} local argPrefix = prefix .. sep do local key = argPrefix .. 'date' t.date = validateDate(key, args[key], articleHistoryObj) t.month, t.day, t.year = t.date:match('(%a+) (%d+), (%d+)') t.day = tonumber(t.day) t.year = tonumber(t.year) t.ymdDate = getYmdDate(t.date) end for _, suffix in ipairs(suffixes) do local key = argPrefix .. suffix t[suffix] = args[key] end t.argPrefix = argPrefix data[#data + 1] = t end if args[prefix .. 'date'] then addData('') end if prefixArgs[prefix] then for _, prefixData in ipairs(prefixArgs[prefix]) do addData(tostring(prefixData[1])) end end if #data < 1 then error(string.format( "no data items found for prefix '%s' and parameter checks failed'", tostring(prefix) )) end return data end -- This makes the text for Main Page features such as DYKs and ITNs for the -- dates contained in dateData (made with the makeDateData function). -- The parameter $1 in the blurb will be replaced with the list of dates. local function makeDateText(dateData, blurb, wantBold) local bold = wantBold and "'''" or "" local dates, doneLinks = {}, {} for i, t in ipairs(dateData) do local date if t.link and not doneLinks[t.link] then date = string.format('[[%s|%s]]', t.link, t.date) doneLinks[t.link] = true else date = t.date end dates[i] = bold .. date .. bold end local dateList = mw.text.listToText(dates, ', ', ', and ') return mw.message.newRawMessage(blurb, dateList):plain() end return { ------------------------------------------------------------------------------- -- CONFIG TABLE START ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -- Statuses -- Configuration for possible current statuses of the article. ------------------------------------------------------------------------------- -- The statuses table contain configuration tables for possible current statuses -- of the article. -- Each table can have the following fields: -- -- id: the main ID for the status. This should be the same as the configuration -- table key. -- aliases: a table of ID aliases that can be used to access the config table. -- icon: The status icon. -- iconSize: The icon size, including "px" suffix. The default is defined in -- defaultStatusIconSize. -- iconMultiSize: The icon size if we are outputting multiple status rows. The -- default is defaultMultiStatusIconSize. -- text: The status text. This may be a string or a function. If it is a -- function, it takes an article history object as input, and should return -- the text string. If it is a string, it can have the following parameters: -- $1 - The full page name of the article or subject page -- $2 - The page name without the namespace name -- categories: The categories set by the status. This may be an array of -- category names, or a function. If it is a function, it takes an article -- history object as the first parameter, and the current status object as -- the second parameter, and should return an array of category objects. -- noticeBarIcon: the icon to use for the notice bar. This can be a string, or -- a function, or true. If it is a function it takes an article history -- object as the first parameter, and should output the icon filename. If it -- is true, it uses the value of icon. If it is nil then no notice bar icon -- will be displayed. -- noticeBarIconCaption: the caption to use for the notice bar icon. The status -- name is used by default. This can be a string or a function. If it is a -- function, it takes an article history object as its first parameter, and -- should return the caption text. If this is absent, the icon caption is -- used instead. -- noticeBarIconSize: the size of the notice bar icon, including "px" suffix. -- The default is set by defaultNoticeBarIconSize. statuses = { FA = { id = 'FA', name = 'Featured article', icon = 'Featured article star.svg', text = function (articleHistoryObj) local articlePage = articleHistoryObj.currentTitle.subjectPageTitle.prefixedText local actions = articleHistoryObj:getActionObjects() local link for i = #actions, 1, -1 do local actionObj = actions[i] if actionObj.id == 'FAC' then link = actionObj.link break end end link = link or 'Wikipedia:Featured article candidates/' .. articlePage local text = "'''%s''' is a [[Wikipedia:Featured articles|featured article]]; " .. "it (or a previous version of it) has been '''[[%s|identified]]''' " .. "as one of the best articles produced by the [[Wikipedia:Wikipedians|Wikipedia community]]. " .. "Even so, if you can update or improve it, [[Wikipedia:Be bold|please do so]]." return string.format(text, articlePage, link) end, categories = {'Wikipedia featured articles'} }, FFA = { id = 'FFA', name = 'Former featured article', icon = 'Featured article star - cross.svg', iconSize = '48px', text = "'''$1''' is a [[Wikipedia:Former featured articles|former featured article]]. " .. "Please see the links under Article milestones below for its original nomination page " .. "(for older articles, check [[Wikipedia:Featured article candidates/Archived nominations/Index|the nomination archive]]) " .. "and why it was removed.", categories = {'Wikipedia former featured articles'} }, FFAC = { id = 'FFAC', name = 'Former featured article candidate', aliases = {'FACFAILED'}, icon = 'Cscr-former.svg', text = "'''$1''' is a former [[Wikipedia:Featured article candidates|featured article candidate]]. " .. "Please view the links under Article milestones below to see why " .. "the nomination failed. For older candidates, please check the " .. "[[Wikipedia:Featured article candidates/Archived nominations/Index|archive]]." }, FL = { id = 'FL', name = 'Featured list', icon = 'Featured article star.svg', iconSize = '48px', text = function (articleHistoryObj) local articlePage = articleHistoryObj.currentTitle.subjectPageTitle.prefixedText local actions = articleHistoryObj:getActionObjects() local link for i = #actions, 1, -1 do local actionObj = actions[i] if actionObj.id == 'FLC' then link = actionObj.link break end end link = link or 'Wikipedia:Featured list candidates/' .. articlePage local text = "'''%s''' is a [[Wikipedia:Featured lists|featured list]], " .. "which means it has been '''[[%s|identified]]''' as one of the best " .. "[[Wikipedia:Stand-alone lists|lists]] produced by the [[Wikipedia:Wikipedians|Wikipedia community]]. " .. "If you can update or improve it, [[Wikipedia:Be bold|please do so]]." return string.format(text, articlePage, link) end, categories = {'Wikipedia featured lists'} }, FFL = { id = 'FFL', name = 'Former featured list', icon = 'Cscr-featured-strike.svg', text = "'''$1''' is a [[Wikipedia:Former featured lists|former featured list]]. " .. "Please see the links under Article milestones below for its original " .. "nomination page and why it was removed. If it has improved again to " .. "[[Wikipedia:Featured list criteria|featured list standard]], you may " .. "[[Wikipedia:Featured list candidates|renominate]] the article to " .. "become a [[Wikipedia:Featured lists|featured list]]." }, FFLC = { id = 'FFLC', name = 'Former featured list candidate', icon = 'Cscr-former.svg', iconCaption = 'Former FLC', text = "'''$1''' is a former [[Wikipedia:Featured list candidates|featured list candidate]]. " .. "Please view the link under Article milestones below to see why the nomination failed. " .. "Once the objections have been addressed you may " .. "[[Wikipedia:Featured list candidates#Resubmitting nominations|resubmit]] " .. "the article for featured list status.", categories = {'Wikipedia featured list candidates (contested)'} }, ['FFA/GA'] = { id = 'FFA/GA', name = 'Former featured article, current good article', isMulti = true, statuses = {'FFA', 'GA'} }, ['FFAC/GA'] = { id = 'FFAC/GA', name = 'Former featured article candidate, current good article', isMulti = true, statuses = {'FFAC', 'GA'} }, GA = { id = 'GA', name = 'Good article', icon = 'Symbol support vote.svg', iconSize = '40px', iconMultiSize = '25px', text = function (articleHistoryObj) local link, display = getGoodArticleTopicLink(articleHistoryObj.args.topic) local articlePage = articleHistoryObj.currentTitle.subjectPageTitle.prefixedText local text = "'''%s''' has been listed as one of the '''''[[%s|%s]]''''' " .. "under the [[Wikipedia:Good article criteria|good article criteria]]. " .. "If you can improve it further, [[Wikipedia:Be bold|please do so]]. " .. "<small>''If it no longer meets these criteria, you can " .. "'''[[Wikipedia:Good article reassessment|reassess]]''' it''.</small>" return string.format(text, articlePage, link, display) end, categories = function (articleHistoryObj) local ret = {} local title = articleHistoryObj.currentTitle if title.namespace == 1 then ret[#ret + 1] = Category.new('Wikipedia good articles') ret[#ret + 1] = Category.new('Wikipedia CD Selection-GAs') local topic = getGoodArticleTopic(articleHistoryObj.args.topic) if topic then ret[#ret + 1] = Category.new( topic .. ' good articles', title.text ) else ret[#ret + 1] = Category.new( 'Good articles without topic parameter', title.text ) end end return ret end }, FGAN = { id = 'FGAN', name = 'Former good article nominee', aliases = {'FAILEDGA'}, icon = 'Symbol unsupport vote.svg', text = function (articleHistoryObj) local articlePage = articleHistoryObj.currentTitle.subjectPageTitle.prefixedText local link, display = getGoodArticleTopicLink(articleHistoryObj.args.topic) local text = "'''%s''' was a '''''[[%s|%s]]''''' nominee, " .. "but did not meet the [[Wikipedia:Good article criteria|good article criteria]] " .. "at the time. There may be suggestions below for improving the article. " .. "Once these issues have been addressed, the article can be " .. "[[Wikipedia:Good article nominations|renominated]]. " .. "Editors may also seek a '''[[Wikipedia:Good article reassessment|reassessment]]''' " .. "of the decision if they believe there was a mistake." return string.format(text, articlePage, link, display) end, categories = {'Former good article nominees'} }, DGA = { id = 'DGA', name = 'Delisted good article', aliases = {'DELISTEDGA'}, icon = 'Symbol unsupport vote.svg', iconCaption = 'Former good article', text = function (articleHistoryObj) local articlePage = articleHistoryObj.currentTitle.subjectPageTitle.prefixedText local link, display = getGoodArticleTopicLink(articleHistoryObj.args.topic) local text = "'''%s''' was one of the '''''[[%s|%s]]''''', " .. "but it has been removed from the list. " .. "There are suggestions below for improving the article to meet the " .. "[[Wikipedia:Good article criteria|good article criteria]]. " .. "Once these issues have been addressed, the article can be " .. "[[Wikipedia:Good article nominations|renominated]]. " .. "Editors may also seek a '''[[Wikipedia:Good article reassessment|reassessment]]''' " .. "of the decision if they believe there was a mistake." return string.format(text, articlePage, link, display) end, categories = {'Delisted good articles'} }, FFT = { id = 'FFT', name = 'Part of former featured topic', icon = 'Cscr-featured-strike.svg', iconCaption = 'Former featured topic', text = "This article is part of a " .. "''[[Wikipedia:Former featured topics|former featured topic]]'' series. " .. "If it has improved again to " .. "[[Wikipedia:Featured topic criteria|featured topic standard]], " .. "you may [[Wikipedia:Featured topic candidates|renominate]] " .. "the topic to become a [[Wikipedia:Featured topic|featured topic]]." }, FFTC = { id = 'FFTC', name = 'Former featured topic candidate', icon = 'Cscr-former.svg', text = "This article is part of a ''former'' " .. "[[Wikipedia:Featured topic candidates|featured topic candidate]]. " .. "Please view the links under Article milestones below to see why " .. "the nomination failed." }, FPO = { id = 'FPO', name = 'Featured portal', icon = 'Cscr-featured.svg', text = "The '''$2 Portal''' is a [[Wikipedia:Featured portals|featured portal]], " .. "which means it has been " .. "'''[[Wikipedia:Featured portal candidates/Portal:$2|identified]]''' " .. "as one of the best portals on [[Wikipedia]]. " .. "If you see a way this portal can be updated or improved without " .. "compromising previous work, please feel free to contribute.", categories = function (articleHistoryObj) return {Category.new( 'Wikipedia featured portals', articleHistoryObj.currentTitle.text )} end }, FFPO = { id = 'FFPO', name = 'Former featured portal', icon = 'Featured article star - cross.svg', text = "This portal is a [[Wikipedia:Former featured portals|former featured portal]]. " .. "Please see the links under Portal milestones below for its " .. "original nomination page and why it was removed.", categories = function (articleHistoryObj) return {Category.new( 'Wikipedia former featured portals', articleHistoryObj.currentTitle.text )} end }, FFPOC = { id = 'FFPOC', name = 'Former featured portal candidate', icon = 'Cscr-former.svg', text = "This portal is a '''''former''''' " .. "[[Wikipedia:Featured portal candidates|featured portal candidate]]. " .. "Please see the links under Portal milestones below for its " .. "original nomination page and why the nomination failed.", categories = function (articleHistoryObj) return {Category.new( 'Wikipedia featured portal candidates (contested)', articleHistoryObj.currentTitle.text )} end }, PR = { -- Peer review is a valid current status, but it doesn't trigger a -- header row. id = 'PR', name = 'Peer reviewed', noticeBarIcon = 'Nuvola apps kedit.svg' }, NA = { -- A valid current status, but doesn't trigger a header row. id = 'NA', noticeBarIcon = 'Nuvola apps kedit.svg' }, -- The following are invalid statuses. FAC = { id = 'FAC', text = function (articleHistoryObj) articleHistoryObj:raiseError( string.format( 'use the template %s to nominate an article for Featured article status', makeTemplateLink('fac') ), 'Template:Article history#Featured article candidates' ) end }, FAR = { id = 'FAR', text = function (articleHistoryObj) articleHistoryObj:raiseError( string.format( 'use the template %s to nominate an article for Featured article review', makeTemplateLink('FAR') ), 'Template:Article history#Featured article review' ) end }, STUB = { id = 'STUB', aliases = {'START', 'B', 'A'}, text = function (articleHistoryObj) local currentStatusParam = articleHistoryObj.cfg.currentStatusParam articleHistoryObj:raiseError( string.format( "do not use '%s' as value of the '%s' parameter; these " .. 'assessments are the responsibility of individual ' .. 'WikiProjects', articleHistoryObj.args[currentStatusParam], currentStatusParam ), 'Template:Article history#WikiProject assessments' ) end }, }, -- This function allows the generation of custom status ID. It takes an -- articleHistory object as the first parameter, and should output the status -- ID. getStatusIdFunction = function (articleHistoryObj) -- Get the status ID. The status code is the code passed in from the -- arguments, and the ID is the value contained in the config. local statusCode = articleHistoryObj.args[articleHistoryObj.cfg.currentStatusParam] local statusId = articleHistoryObj:getStatusIdForCode(statusCode) -- Check for former featured articles. if statusId ~= 'FA' and statusId ~= 'FL' and statusId ~= 'FFA' and statusId ~= 'FFL' and statusId ~= 'FFA/GA' then local ffaObj local actions = articleHistoryObj:getActionObjects() for i = #actions, 1, -1 do local actionObj = actions[i] if actionObj.id == 'FAR' and actionObj.resultId == 'demoted' then ffaObj = actionObj break end end if ffaObj then if not statusId then articleHistoryObj:raiseError( 'former featured articles should have a current status', 'Template:Article history#Former featured articles' ) elseif statusId == 'GA' then statusId = 'FFA/GA' elseif statusId == 'DGA' then statusId = 'FFA' else articleHistoryObj:raiseError( string.format( "'%s' is not a valid current status for former featured articles", tostring(statusCode) ), 'Template:Article history#Former featured articles' ) end end end return statusId end, ------------------------------------------------------------------------------- -- Notices ------------------------------------------------------------------------------- -- The notices table contains configuration tables for notices about the article -- that are unrelated to its current status. -- Each configuration table can have the following fields: -- -- id: the main ID for the notice. This should be the same as the configuration -- table key. -- isActive: a function that should return a truthy value if the notice should -- be displayed, and a falsy value if not. (Falsy values are false and nil, -- and truthy values are everything else.) The function takes an article -- history object as its first parameter. -- makeData: a function that should return a table of data to be used by other -- functions in this notice configuration table. It can be accessed using -- noticeObj:getData(). -- icon: the filename of the notice icon, minus the "File:" prefix. -- iconCaption: the icon caption. -- iconSize: The icon size, including "px" suffix. The default is defined in -- defaultIconSize. -- text: The notice text. This may be a string or a function. If it is a -- function, it takes an article history object as the first parameter, and -- the current notice object as the second parameter, and should return the -- text string. -- categories: The categories set by the notice. This may be an array of -- category names, or a function. If it is a function, it takes an article -- history object as the first parameter, and the current notice object as -- the second parameter, and should return an array of category objects. -- noticeBarIcon: the icon to use for the notice bar. This can be a string, or -- a function, or true. If it is a function it takes an article history -- object as the first parameter, and should output the icon filename. If it -- is true, it uses the value of icon. If it is nil then no notice bar icon -- will be displayed. -- noticeBarIconCaption: the caption to use for the notice bar icon. This can be -- a string or a function. If it is a function, it takes an article history -- object as its first parameter, and should return the caption text. If this -- is absent, the icon caption is used instead. -- noticeBarIconSize: the size of the notice bar icon, including "px" suffix. -- The default is set by defaultNoticeBarIconSize. notices = { { id = 'FT', isActive = function (articleHistoryObj) local args = articleHistoryObj.args local prefixArgs = articleHistoryObj.prefixArgs -- ftmain is included here because it leads to better error -- messages than leaving it out, even though ftmain by itself is -- invalid. return args.ftname or args.ftmain or prefixArgs.ft end, makeData = function (articleHistoryObj) local args = articleHistoryObj.args local prefixArgs = articleHistoryObj.prefixArgs local data = {} local getTopicStatus = require('Module:FeaturedTopicSum').status local yesno = require('Module:Yesno') local function makeTopicData(name, isMain, paramNum) if name then return { name = name, isMain = yesno(isMain) or false, status = getTopicStatus(name), paramNum = paramNum } elseif isMain then local num = paramNum and tostring(paramNum) or '' articleHistoryObj:raiseError( string.format( "parameter 'ft%smain' is set, but no featured " .. "topic name is set in parameter 'ft%sname'", num, num ), 'Template:Article history#Featured topic names' ) else return nil end end data[#data + 1] = makeTopicData(args.ftname, args.ftmain) if prefixArgs.ft then for _, t in ipairs(prefixArgs.ft) do if t[1] > 1 then -- we use args.ftname instead of args.ft1name data[#data + 1] = makeTopicData(t.name, t.main, t[1]) end end end -- Check for rogue ft.. parameters if #data < 1 then articleHistoryObj:raiseError( "a parameter starting with 'ft' was detected, but no " .. "featured topic names were specified; " .. "please check the parameter names", 'Template:Article history#Featured topic names' ) end -- Find if one of the topics is featured. local isInFeaturedTopic = false for _, topic in ipairs(data) do if topic.status == 'FT' then isInFeaturedTopic = true break end end data.isInFeaturedTopic = isInFeaturedTopic return data end, icon = function (articleHistoryObj, noticeObj) local data = noticeObj:getData(articleHistoryObj) if not data then return nil end if data.isInFeaturedTopic then return 'Cscr-featuredtopic.svg' else return 'Support cluster.svg' end end, iconCaption = function (articleHistoryObj, noticeObj) local data = noticeObj:getData(articleHistoryObj) if not data then return nil end if data.isInFeaturedTopic then return 'Featured topic star' else return 'Good topic star' end end, iconSize = '48px', text = function (articleHistoryObj, noticeObj) local data = noticeObj:getData(articleHistoryObj) if not data then return nil end local article = articleHistoryObj.currentTitle.subjectPageTitle.prefixedText local firstBlurb = "'''%s''' is %s the '''[[Wikipedia:Featured topics/%s|%s]] series''', %s." local otherBlurb = "It is also %s the '''[[Wikipedia:Featured topics/%s|%s]] series''', %s." local finalBlurb = "%s identified as among the best series of " .. "articles produced by the [[Wikipedia:Wikipedians|Wikipedia community]]. " .. "If you can update or improve %s, [[Wikipedia:Be bold|please do so]]." local main = 'the main article in' local notMain = 'part of' local featuredLink = 'a [[Wikipedia:Featured topics|featured topic]]' local featuredNoLink = 'a featured topic' local goodLink = 'a [[Wikipedia:Good topics|good topic]]' local goodNoLink = 'a good topic' local thisSingular = 'This is' local thisPlural = 'These are' local itSingular = 'it' local itPlural = 'them' local hasFeaturedLink = false local hasGoodLink = false local text = {} -- First topic do local topic = data[1] local link if topic.status == 'FT' then link = featuredLink hasFeaturedLink = true else link = goodLink hasGoodLink = true end text[#text + 1] = string.format( firstBlurb, article, topic.isMain and main or notMain, topic.name, topic.name, link ) end -- Other topics for i = 2, #data do local topic = data[i] local link if topic.status == 'FT' then if hasFeaturedLink then link = featuredNoLink else link = featuredLink hasFeaturedLink = true end else if hasGoodLink then link = goodNoLink else link = goodLink hasGoodLink = true end end text[#text + 1] = string.format( otherBlurb, topic.isMain and main or notMain, topic.name, topic.name, link ) end -- Final blurb do local isPlural = #data > 1 text[#text + 1] = string.format( finalBlurb, isPlural and thisPlural or thisSingular, isPlural and itPlural or itSingular ) end return table.concat(text, ' ') end, categories = function (articleHistoryObj, noticeObj) local data = noticeObj:getData(articleHistoryObj) if not data then return nil end local status = articleHistoryObj:getStatusId() local article = articleHistoryObj.currentTitle.subjectPageTitle.prefixedText local cats = {} local function addCat(cat, sort) cats[#cats + 1] = Category.new(cat, sort) end -- Page-wide status categories if status == 'FA' then addCat('FA-Class Featured topics articles') elseif status == 'FL' then addCat('FL-Class Featured topics articles') elseif status == 'FFA/GA' or status == 'FFAC/GA' or status == 'GA' then addCat('GA-Class Featured topics articles') else addCat('Unassessed Featured topics articles') end -- Topic-specific status categories local function addTopicCats(catFormat) for _, topic in ipairs(data) do addCat(string.format(catFormat, topic.name)) end end if status == 'FA' or status == 'FL' then addTopicCats('Wikipedia featured topics %s featured content') elseif status == 'FFA/GA' or 'GA' then addTopicCats('Wikipedia featured topics %s good content') else addTopicCats('Wikipedia featured topics %s') end -- Importance categories local hasTop, hasHigh, hasMid, hasLow -- These check for dupes for _, topic in ipairs(data) do local cat, sort if topic.status == 'FT' then if topic.isMain and not hasTop then cat = 'Top-importance Featured topics articles' sort = topic.name .. ' ' .. article hasTop = true elseif not topic.isMain and not hasHigh then cat = 'High-importance Featured topics articles' hasHigh = true end else if topic.isMain and not hasMid then cat = 'Mid-importance Featured topics articles' sort = topic.name .. ' ' .. article hasMid = true elseif not topic.isMain and not hasLow then cat = 'Low-importance Featured topics articles' hasLow = true end end if cat then addCat(cat, sort) end end return cats end }, -- Main page date { id = 'MAINDATE', isActive = function (articleHistoryObj) local args = articleHistoryObj.args local status = articleHistoryObj:getStatusId() return args.maindate or status == 'FA' or status == 'FL' end, makeData = function (articleHistoryObj) local args = articleHistoryObj.args local status = articleHistoryObj:getStatusId() local data = {} local function validateMainDate(argName, dataName, dataTimestampName) data[dataName] = args[argName] if data[dataName] then data[dataTimestampName] = getYmdDate(data[dataName]) if not data[dataTimestampName] then articleHistoryObj:raiseError( string.format( "invalid date '%s' detected in parameter '%s'", data[dataName], argName ), 'Template:Article history#Invalid date' ) end end end validateMainDate('maindate', 'mainDate', 'mainDateTimestamp') if data.mainDate then validateMainDate('maindate2', 'mainDate2', 'mainDate2Timestamp') if data.mainDate2 and data.mainDateTimestamp >= data.mainDate2Timestamp then articleHistoryObj:raiseError( "the date in the 'maindate' parameter must be earlier than the date in the 'maindate2' parameter", 'Template:Article history#Main Page date order' ) end end data.currentTimestamp = getYmdDate() -- Whether the page is a list or not for the purposes of the Main -- Page. The first Today's Featured List was on 13 June 2011, so -- lists that were featured before then count as articles. data.isList = (status == 'FL' or status == 'FFL') and (not data.mainDate or data.mainDateTimestamp >= 20110613) return data end, icon = 'Wikipedia-logo-v2.svg', iconCaption = 'Main Page trophy', text = function (articleHistoryObj, noticeObj) local data = noticeObj:getData(articleHistoryObj) if not data or not data.mainDate then return nil end -- Build the blurb for all the possible combinations of past, -- present and future appearances of maindate and maindate2. local pagetype = data.isList and 'list' or 'article' local mainDateLong = getLongDate(data.mainDate) local mainDate2Long = data.mainDate2 and getLongDate(data.mainDate2) local todaysFA = "Today's featured " .. pagetype local function makeFeaturedLink(date, display) return string.format( "[[Wikipedia:Today's featured %s/%s|%s]]", pagetype, date, display or date ) end local function isPast(timestamp) return timestamp < data.currentTimestamp end local function isCurrent(timestamp) return timestamp == data.currentTimestamp end local function isFuture(timestamp) return timestamp > data.currentTimestamp end if data.mainDate2 then if isPast(data.mainDateTimestamp) then if isPast(data.mainDate2Timestamp) then return string.format( "This article appeared on Wikipedia's Main Page as %s on %s, and on %s.", todaysFA, makeFeaturedLink(mainDateLong), makeFeaturedLink(mainDate2Long) ) elseif isCurrent(data.mainDate2Timestamp) then return string.format( "This article is currently on Wikipedia's Main Page as %s. It also appeared previously on %s.", makeFeaturedLink(mainDate2Long, todaysFA), makeFeaturedLink(mainDateLong) ) else return string.format( "This article appeared on Wikipedia's Main Page as %s on %s, and will appear again on %s.", todaysFA, makeFeaturedLink(mainDateLong), makeFeaturedLink(mainDate2Long) ) end elseif isCurrent(data.mainDateTimestamp) then if isFuture(data.mainDate2Timestamp) then return string.format( "This article is currently on Wikipedia's Main Page as %s, and will appear again on %s.", makeFeaturedLink(mainDateLong, todaysFA), makeFeaturedLink(mainDate2Long) ) else return nil end else if isFuture(data.mainDate2Timestamp) then return string.format( "This article will appear on Wikipedia's Main Page as %s on %s, and again on %s.", todaysFA, makeFeaturedLink(mainDateLong), makeFeaturedLink(mainDate2Long) ) else return nil end end else if isPast(data.mainDateTimestamp) then return string.format( "This article appeared on Wikipedia's Main Page as %s on %s.", makeFeaturedLink(mainDateLong, todaysFA), mainDateLong ) elseif isCurrent(data.mainDateTimestamp) then return string.format( "This article is currently on Wikipedia's Main Page as %s.", makeFeaturedLink(mainDateLong, todaysFA), mainDateLong ) else return string.format( "This article will appear on Wikipedia's Main Page as %s on %s.", makeFeaturedLink(mainDateLong, todaysFA), mainDateLong ) end end end, categories = function (articleHistoryObj, noticeObj) local data = noticeObj:getData(articleHistoryObj) if not data then return nil end local status = articleHistoryObj:getStatusId() local cats = {} local pagetype = data.isList and 'lists' or 'articles' if data.mainDate and data.mainDateTimestamp <= data.currentTimestamp then cats[#cats + 1] = Category.new(string.format( 'Featured %s that have appeared on the main page', pagetype )) if data.mainDate2 and data.mainDate2Timestamp <= data.currentTimestamp then cats[#cats + 1] = Category.new(string.format( 'Featured %s that have appeared on the main page twice', pagetype )) else cats[#cats + 1] = Category.new(string.format( 'Featured %s that have appeared on the main page once', pagetype )) end elseif status == 'FA' or status == 'FL' or data.mainDate then cats[#cats + 1] = Category.new(string.format( 'Featured %s that have not appeared on the main page', pagetype )) end return cats end } }, ------------------------------------------------------------------------------- -- Actions ------------------------------------------------------------------------------- -- The actions table contains configuration tables for actions such as featured -- article candidacies and peer review, etc. -- Each configuration table can have the following fields: -- -- id: the main ID for the action. This should be the same as the configuration -- table key. -- name: the name of the action. This can be a string or a function. If it is -- a function, it takes an article history object as its first parameter and -- the action object as its second parameter, and should return the name. -- results: a table of possible results for the action. Keys in the table should -- be a result ID, e.g. "promoted" or "kept", and values should be a subtable -- with the following fields: -- id: the result ID. This should be the same as the table key. It will -- also define a possible input value for the action's result parameter. -- text: the displayed result text. This may be a string or a function. If it -- is a function, it takes an article history object as the first -- parameter and the current action object as the second parameter, and -- should return the result string. -- aliases: an array of result ID aliases. Each of these will define a valid -- value for the action's result parameter. -- text: The action text. This may be a string or a function. If it is a -- function, it takes an article history object as the first parameter and -- the current action object as the second parameter, and should return the -- text string. -- categories: The categories set by the notice. This may be an array of -- category names, or a function. If it is a function, it takes an article -- history object as the first parameter and the current action object as the -- second parameter, and should return an array of category objects. -- noticeBarIcon: the icon to use for the notice bar. This can be a string, or -- a function, or true. If it is a function it takes an article history -- object as the first parameter, and should output the icon filename. If it -- is true, it uses the value of icon. If it is nil then no notice bar icon -- will be displayed. -- noticeBarIconCaption: the caption to use for the notice bar icon. This can be -- a string or a function. If it is a function, it takes an article history -- object as its first parameter, and should return the caption text. If this -- is absent, the icon caption is used instead. -- noticeBarIconSize: the size of the notice bar icon, including "px" suffix. -- The default is set by defaultNoticeBarIconSize. actions = { FAC = { id = 'FAC', name = 'Featured article candidate', results = { promoted = { id = 'promoted', text = 'Promoted', aliases = {'pass', 'passed'} }, ['not promoted'] = { id = 'not promoted', text = 'Not promoted', aliases = {'fail', 'failed'} } } }, FAR = { id = 'FAR', name = 'Featured article review', aliases = {'FARC'}, results = { kept = { id = 'kept', text = 'Kept', aliases = {'pass', 'passed', 'keep'} }, demoted = { id = 'demoted', text = 'Demoted', aliases = {'fail', 'failed', 'remove', 'removed'} }, merged = { id = 'merged', text = 'Merged', aliases = {'merge'} } }, categories = function (articleHistoryObj, actionObj) local ret = {} local result = actionObj.resultId if result == 'demoted' or result == 'merged' then local status = articleHistoryObj:getStatusId() local sortKey = articleHistoryObj.currentTitle.subjectPageTitle.prefixedText if status == 'FA' or status == 'FL' then sortKey = '#' .. sortKey end ret[#ret + 1] = Category.new( 'Wikipedia former featured articles', sortKey ) end return ret end }, BP = { id = 'BP', name = 'Brilliant prose', results = { nominated = { id = 'nominated', text = 'Nominated', aliases = {'pass', 'promoted', 'nom'} } } }, RBP = { id = 'RBP', name = 'Refreshing brilliant prose', results = { kept = { id = 'kept', text = 'Kept', aliases = {'pass', 'passed', 'keep'} }, ['not kept'] = { id = 'not kept', text = 'Not kept', aliases = {'fail', 'failed', 'remove', 'removed', 'demoted'} } }, categories = function (articleHistoryObj, actionObj) local ret = {} if actionObj.resultId == 'not kept' then ret[#ret + 1] = Category.new( 'Wikipedia former brilliant prose', articleHistoryObj.currentTitle.text ) end return ret end }, FLC = { id = 'FLC', name = 'Featured list candidate', results = { promoted = { id = 'promoted', text = 'Promoted', aliases = {'pass', 'passed'} }, ['not promoted'] = { id = 'not promoted', text = 'Not promoted', aliases = {'fail', 'failed'} } } }, FLR = { id = 'FLR', name = 'Featured list removal candidate', results = { kept = { id = 'kept', text = 'Kept', aliases = {'pass', 'passed', 'keep'} }, demoted = { id = 'demoted', text = 'Demoted', aliases = {'fail', 'failed', 'remove', 'removed'} }, merged = { id = 'merged', text = 'Merged', aliases = {'merge'} } }, categories = function (articleHistoryObj, actionObj) local ret = {} local result = actionObj.resultId if result == 'demoted' or result == 'merged' then local sortKey if articleHistoryObj:getStatusId() == 'FL' then sortKey = '#' .. articleHistoryObj.currentTitle.subjectPageTitle.prefixedText else sortKey = articleHistoryObj.currentTitle.text end ret[#ret + 1] = Category.new( 'Wikipedia former featured lists', sortKey ) end return ret end }, FTC = { id = 'FTC', name = 'Featured topic candidate', results = { promoted = { id = 'promoted', text = 'Promoted', aliases = {'pass', 'passed'} }, ['not promoted'] = { id = 'not promoted', text = 'Not promoted', aliases = {'fail', 'failed'} } } }, FTR = { id = 'FTR', name = 'Featured topic removal candidate', results = { kept = { id = 'kept', text = 'Kept', aliases = {'pass', 'passed', 'keep'} }, demoted = { id = 'demoted', text = 'Demoted', aliases = {'fail', 'failed', 'remove', 'removed'} }, merged = { id = 'merged', text = 'Merged', aliases = {'merge'} } } }, FPOC = { id = 'FPOC', name = 'Featured portal candidate', results = { promoted = { id = 'promoted', text = 'Promoted', aliases = {'pass', 'passed'} }, ['not promoted'] = { id = 'not promoted', text = 'Not promoted', aliases = {'fail', 'failed'} } } }, FPOR = { id = 'FPOR', name = 'Featured portal review', results = { kept = { id = 'kept', text = 'Kept', aliases = {'pass', 'passed', 'keep'} }, demoted = { id = 'demoted', text = 'Demoted', aliases = {'fail', 'failed', 'remove', 'removed'} }, merged = { id = 'merged', text = 'Merged', aliases = {'merge'} } } }, GAN = { id = 'GAN', name = 'Good article nominee', aliases = {'GAC'}, results = { listed = { id = 'listed', text = 'Listed', aliases = {'pass', 'passed', 'promoted'} }, ['not listed'] = { id = 'not listed', text = 'Not listed', aliases = {'fail', 'failed', 'not promoted'} } }, categories = function (articleHistoryObj, actionObj) local ret = {} if actionObj.resultId == 'not listed' then local status = articleHistoryObj:getStatusId() if status ~= 'FA' and status ~= 'GA' and status ~= 'FFA' then ret[#ret + 1] = Category.new( 'Former good article nominees', articleHistoryObj.currentTitle.text ) end end return ret end }, GAR = { id = 'GAR', name = 'Good article reassessment', results = { kept = { id = 'kept', text = 'Kept', aliases = {'pass', 'passed', 'keep'} }, delisted = { id = 'delisted', text = 'Delisted', aliases = {'fail', 'failed'} }, listed = { id = 'listed', text = 'Listed' }, ['not listed'] = { id = 'not listed', text = 'Not listed' } }, categories = function (articleHistoryObj, actionObj) local ret = {} if actionObj.resultId == 'delisted' then local status = articleHistoryObj:getStatusId() if status ~= 'FA' and status ~= 'GA' then ret[#ret + 1] = Category.new( 'Delisted good articles', articleHistoryObj.currentTitle.text ) end end end }, GTC = { id = 'GTC', name = 'Good topic candidate', results = { promoted = { id = 'promoted', text = 'Promoted', aliases = {'pass', 'passed'} }, ['not promoted'] = { id = 'not promoted', text = 'Not promoted', aliases = {'fail', 'failed'} } } }, GTR = { id = 'GTR', name = 'Good topic removal candidate', results = { kept = { id = 'kept', text = 'Kept', aliases = {'pass', 'passed', 'keep'} }, demoted = { id = 'demoted', text = 'Demoted', aliases = {'fail', 'failed', 'remove', 'removed'} }, merged = { id = 'merged', text = 'Merged', aliases = {'merge'} } } }, PR = { id = 'PR', name = 'Peer review', results = { reviewed = { id = 'reviewed', text = 'Reviewed', aliases = {'_BLANK'} }, ['not reviewed'] = { id = 'not reviewed', text = 'Not reviewed', } }, categories = {'Old requests for peer review'} }, WPR = { id = 'WPR', name = function (articleHistoryObj, actionObj) local names = { approved = 'WikiProject approved revision', copyedited = 'Guild of Copy Editors', collaboration = 'WikiProject collaboration', maindate = "Today's featured article" } local result = actionObj.resultId return result and names[result] or 'WikiProject peer review' end, results = { approved = { id = 'approved', text = function(articleHistoryObj, actionObj) if actionObj.oldid then local url = mw.uri.fullUrl( articleHistoryObj.currentTitle.prefixedText, {diff = 'cur', oldid = actionObj.oldid} ) return string.format( '[%s %s]', tostring(url), 'Diff to current version' ) else error(string.format( "No oldid detected for the approved version; " .. "please set the 'action%doldid' parameter " .. "or give the 'action%dresult' parameter a " .. "different value.", actionObj.paramNum, actionObj.paramNum )) end end, aliases = {'approved version'} }, copyedited = { id = 'copyedited', text = 'Copyedited', aliases = {'copyedit', 'proofread'} }, maindate = { id = 'maindate', text = 'Main Page' }, collaborated = { id = 'collaborated', text = 'Collaborated', aliases = {'cotw', 'collaboration'} }, reviewed = { id = 'reviewed', text = 'Reviewed', aliases = {'_BLANK'} } }, categories = function (articleHistoryObj, actionObj) local ret = {} local result = actionObj.resultId if result == 'copyedited' then ret[1] = Category.new('Articles copy edited by the Guild of Copy Editors') end return ret end }, WAR = { id = 'WAR', name = 'WikiProject A-class review', results = { approved = { id = 'approved', text = 'Approved', aliases = {'pass', 'passed'} }, ['not approved'] = { id = 'not approved', text = 'Not approved', aliases = {'fail', 'failed', 'not reviewed'} }, reviewed = { id = 'reviewed', text = 'Reviewed', aliases = {'_BLANK'} }, kept = { id = 'kept', text = 'Kept', aliases = {'keep'} }, demoted = { id = 'demoted', text = 'Demoted', aliases = {'demote'} } } }, AFD = { id = 'AFD', name = 'Articles for deletion', results = { kept = { id = 'kept', text = 'Kept', aliases = {'withdrawn', 'keep'} }, deleted = { id = 'deleted', text = 'Deleted', aliases = {'delete'} }, merged = { id = 'merged', text = 'Merged', aliases = {'merge'} }, ['no consensus'] = { id = 'no consensus', text = 'No consensus' }, ['speedily kept'] = { id = 'speedily kept', text = 'Speedily kept', aliases = {'speedy keep'} }, ['speedily deleted'] ={ id = 'speedily deleted', text = 'Speedily deleted', aliases = {'speedy delete'} }, redirected = { id = 'redirected', text = 'Redirected', aliases = {'redirect'} }, renamed = { id = 'renamed', text = 'Renamed', aliases = {'rename', 'move', 'moved'} }, } }, MFD = { id = 'MFD', name = 'Miscellany for deletion', results = { kept = { id = 'kept', text = 'Kept', aliases = {'withdrawn', 'keep'} }, deleted = { id = 'deleted', text = 'Deleted', aliases = {'delete'} }, merged = { id = 'merged', text = 'Merged', aliases = {'merge'} }, ['no consensus'] = { id = 'no consensus', text = 'No consensus' }, ['speedily kept'] = { id = 'speedily kept', text = 'Speedily kept', aliases = {'speedy keep'} }, ['speedily deleted'] = { id = 'speedily deleted', text = 'Speedily deleted', aliases = {'speedy delete'} }, redirected = { id = 'redirected', text = 'Redirected', aliases = {'redirect'} }, renamed = { id = 'renamed', text = 'Renamed', aliases = {'rename', 'move', 'moved'} }, } }, TFD = { id = 'TFD', name = 'Templates for discussion', results = { kept = { id = 'kept', text = 'Kept', aliases = {'withdrawn', 'keep'} }, deleted = { id = 'deleted', text = 'Deleted', aliases = {'delete'} }, merged = { id = 'merged', text = 'Merged', aliases = {'merge'} }, ['no consensus'] = { id = 'no consensus', text = 'No consensus' }, ['speedily kept'] = { id = 'speedily kept', text = 'Speedily kept', aliases = {'speedy keep'} }, ['speedily deleted'] = { id = 'speedily deleted', text = 'Speedily deleted', aliases = {'speedy delete'} }, redirected = { text = 'Redirected', aliases = {'redirect'} }, renamed = { id = 'renamed', text = 'Renamed', aliases = {'rename', 'move', 'moved'} }, } }, CSD = { id = 'CSD', name = 'Candidate for speedy deletion', results = { kept = { id = 'kept', text = 'Kept', aliases = {'withdrawn', 'keep'} }, deleted = { id = 'deleted', text = 'Deleted', aliases = {'delete', 'speedily deleted', 'speedy delete'} }, ['speedily kept'] = { id = 'speedily kept', text = 'Speedily kept', aliases = {'speedy keep'} }, redirected = { id = 'redirected', text = 'Redirected', aliases = {'redirect'} }, prod = { id = 'prod', text = 'Converted to [[WP:PROD|proposed deletion]]', aliases = {'prodded'} }, afd = { id = 'afd', text = 'Sent to [[WP:AFD|articles for deletion]]', aliases = {'afded'} }, renamed = { id = 'renamed', text = 'Renamed', aliases = {'rename', 'move', 'moved'} }, } }, PROD = { id = 'PROD', name = 'Proposed deletion', results = { kept = { id = 'kept', text = 'Kept', aliases = {'withdrawn', 'keep'} }, deleted = { id = 'deleted', text = 'Deleted', aliases = {'delete'} }, ['speedily kept'] = { id = 'speedily kept', text = 'Speedily kept', aliases = {'speedy keep'} }, ['speedily deleted'] = { id = 'speedily deleted', text = 'Speedily deleted', aliases = {'speedy delete'} }, redirected = { id = 'redirected', text = 'Redirected', aliases = {'redirect'} }, afd = { id = 'afd', text = 'Sent to [[WP:AFD|articles for deletion]]', aliases = {'afded'} }, renamed = { id = 'renamed', text = 'Renamed', aliases = {'rename', 'move', 'moved'} }, } }, DRV = { id = 'DRV', name = 'Deletion review', results = { endorsed = { id = 'endorsed', text = 'Endorsed', aliases = {'endorse'} }, relisted = { id = 'relisted', text = 'Relisted', aliases = {'relist'} }, overturned = { id = 'overturned', text = 'Overturned', aliases = {'overturn'} }, restored = { id = 'restored', text = 'Restored', aliases = {'restore'} }, ['no consensus'] = { id = 'no consensus', text = 'No consensus' } } } }, ------------------------------------------------------------------------------- -- Collapsible notices ------------------------------------------------------------------------------- -- The collapsibleNotices table contains configuration tables for notices that -- go in the collapsible part of the template, underneath the actions. -- Each configuration table can have the following fields: -- -- id: the main ID for the notice. This should be the same as the configuration -- table key. -- isActive: a function that should return a truthy value if the notice should -- be displayed, and a falsy value if not. (Falsy values are false and nil, -- and truthy values are everything else.) The function takes an article -- history object as its first parameter. -- makeData: a function that should return a table of data to be used by other -- functions in this notice configuration table. It can be accessed using -- noticeObj:getData(). -- icon: the filename of the notice icon, minus the "File:" prefix. -- iconCaption: the icon caption. -- iconSize: The icon size, including "px" suffix. The default is defined in -- defaultIconSize. -- text: The notice text. This may be a string or a function. If it is a -- function, it takes an article history object as the first parameter, and -- the current collapsible notice object as the second parameter, and should -- return the text string. -- categories: The categories set by the notice. This may be an array of -- category names, or a function. If it is a function, it takes an article -- history object as the first parameter, and the current collapsible notice -- object as the second parameter, and should return an array of category -- objects. -- noticeBarIcon: the icon to use for the notice bar. This can be a string, or -- a function, or true. If it is a function it takes an article history -- object as the first parameter, and should output the icon filename. If it -- is true, it uses the value of icon. If it is nil then no notice bar icon -- will be displayed. -- noticeBarIconCaption: the caption to use for the notice bar icon. This can be -- a string or a function. If it is a function, it takes an article history -- object as its first parameter, and should return the caption text. If this -- is absent, the icon caption is used instead. -- noticeBarIconSize: the size of the notice bar icon, including "px" suffix. -- The default is set by defaultNoticeBarIconSize. collapsibleNotices = { -- DYK { id = 'DYK', icon = 'Symbol question.svg', iconCaption = 'Did You Know', noticeBarIcon = true, isActive = function (articleHistoryObj) return isActiveDatedObject(articleHistoryObj, 'dyk') end, makeData = function (articleHistoryObj) return makeDateData(articleHistoryObj, 'dyk', {'entry', 'nom', 'ignoreerror'}) end, text = function (articleHistoryObj, collapsibleNoticeObj) local data = collapsibleNoticeObj:getData(articleHistoryObj) if not data then return nil end for _, t in ipairs(data) do local raPage = 'Wikipedia:Recent additions/' .. getDate('Y/F#j F Y', t.date) if not titleExists(raPage) then raPage = 'Wikipedia:Recent additions' end t.link = raPage end local fact = 'fact from this article' if data[1].nom then fact = '[[' .. data[1].nom .. '|' .. fact .. ']]' end local blurb = "A " .. fact .. " appeared on " .. "Wikipedia's [[Main Page]] in the " .. "''\"[[:Template:Did you know|Did you know?]]\"'' " .. "column on $1." return makeDateText(data, blurb, true) end, collapsibleText = function (articleHistoryObj, collapsibleNoticeObj) local data = collapsibleNoticeObj:getData(articleHistoryObj) if not data then return nil end local ctext = {} if #data == 1 and data[1].entry then ctext[#ctext + 1] = string.format( "The text of the entry was: ''Did you know %s''", data[1].entry ) else local entries = {} local lastEntryDate for _, t in ipairs(data) do entries[#entries + 1] = t.entry lastEntryDate = t.date end if #entries == 1 then ctext[#ctext + 1] = string.format( "The text of the entry for %s was: ''Did you know %s''", lastEntryDate, entries[1] ) elseif #entries > 1 then ctext[#ctext + 1] = 'The text of the entries was:\n' local list = mw.html.create('ul') for _, t in ipairs(data) do if t.entry then list:tag('li'):wikitext(string.format( "%s: ''Did you know %s''", t.date, t.entry )) end end ctext[#ctext + 1] = tostring(list) end end if #ctext > 0 then return table.concat(ctext) else return nil end end, categories = function (articleHistoryObj, collapsibleNoticeObj) local data = collapsibleNoticeObj:getData(articleHistoryObj) if not data then return nil end local cats = {} do local status = articleHistoryObj:getStatusId() local statusCat if status == 'FA' then statusCat = 'Wikipedia Did you know articles that are featured articles' elseif status == 'FL' then statusCat = 'Wikipedia Did you know articles that are featured lists' elseif status == 'GA' or status == 'FFA/GA' then statusCat = 'Wikipedia Did you know articles that are good articles' else statusCat = 'Wikipedia Did you know articles' end cats[#cats + 1] = Category.new(statusCat) end for _, t in ipairs(data) do if not t.ignoreerror then if t.entry then local mCheckDYKEntry = require('Module:Check DYK hook') if not mCheckDYKEntry._isValidHook(t.entry) then cats[#cats + 1] = Category.new('Pages with a malformed DYK entry') end else cats[#cats + 1] = Category.new('Pages with a missing DYK entry') end end end return cats end }, -- ITN { id = 'ITN', isActive = function (articleHistoryObj) return isActiveDatedObject(articleHistoryObj, 'itn') end, makeData = function (articleHistoryObj) return makeDateData(articleHistoryObj, 'itn', {'link'}) end, icon = 'Globe current.svg', iconCaption = 'In the news', noticeBarIcon = true, noticeBarIconSize = '20px', text = function (articleHistoryObj, collapsibleNoticeObj) local data = collapsibleNoticeObj:getData(articleHistoryObj) if not data then return nil end local dates = {} for _, t in ipairs(data) do local date = {} if t.link then date.link = t.link elseif t.ymdDate >= 20110701 then date.link = string.format( 'Wikipedia:In the news/Candidates/%s %d', t.month, t.year ) elseif t.ymdDate >= 20090101 then date.link = string.format( 'Wikipedia:ITN archives/%d/%s', t.year, t.month ) elseif t.ymdDate >= 20050101 then date.link = string.format( 'Portal:Current events/%d %s %d', t.year, t.month, t.day ) end date.date = t.date dates[#dates + 1] = date end local intro if #data > 1 then intro = 'News items involving this article were' else intro = 'A news item involving this article was' end local blurb = intro .. " featured on Wikipedia's [[Main Page]] in the " .. "''\"[[Template:In the news|In the news]]\"'' column on $1." return makeDateText(dates, blurb) end, categories = function (articleHistoryObj, collapsibleNoticeObj) local cats = {} cats[1] = Category.new('Wikipedia In the news articles') return cats end }, -- On This Day { id = 'OTD', isActive = function (articleHistoryObj) return isActiveDatedObject(articleHistoryObj, 'otd') end, makeData = function (articleHistoryObj) return makeDateData(articleHistoryObj, 'otd', {'link', 'oldid'}) -- TODO: remove 'link' after it is no longer needed for tracking end, icon = 'Nuvola apps date.svg', iconCaption = 'On this day...', noticeBarIcon = true, noticeBarIconSize = '20px', text = function (articleHistoryObj, collapsibleNoticeObj) local data = collapsibleNoticeObj:getData(articleHistoryObj) if not data then return nil end local dates = {} for _, t in ipairs(data) do local date = {} date.date = t.date date.link = t.link if t.oldid then -- TODO: Move this inside the main module local oldid = tonumber(t.oldid) if oldid and math.floor(oldid) == oldid and oldid > 0 and oldid < math.huge then -- If the oldid is valid, it takes precedence over -- explicit links. date.link = 'Special:PermaLink/' .. t.oldid else collapsibleNoticeObj:addWarning( string.format( "invalid oldid '%s' detected in parameter '%s'; " .. "if an oldid is specified it must be a positive integer", t.oldid, t.argPrefix .. 'oldid' ), 'Template:Article history#Invalid oldid' ) end end dates[#dates + 1] = date end local intro if #data > 1 then intro = 'Facts from this article were' else intro = 'A fact from this article was' end local blurb = intro .. " featured on Wikipedia's [[Main Page]] in the " .. "''\"[[Wikipedia:Selected anniversaries|On this day...]]\"'' " .. "column on $1." return makeDateText(dates, blurb) end, categories = function (articleHistoryObj, collapsibleNoticeObj) local cats = {} cats[1] = Category.new('Selected anniversaries articles') local data = collapsibleNoticeObj:getData(articleHistoryObj) if data then for _, t in ipairs(data) do if t.link then cats[#cats + 1] = Category.new( 'Article history templates with linked otd dates' ) break end end end return cats end }, -- Article Collaboration and Improvement Drive { id = 'ACID', isActive = function (articleHistoryObj) return articleHistoryObj.args.aciddate end, icon = 'Article Collaboration and Improvement Drive.svg', iconCaption = 'Article Collaboration and Improvement Drive', noticeBarIcon = true, noticeBarIconSize = '20px', text = function (articleHistoryObj) local args = articleHistoryObj.args local blurb = 'This article was on the ' .. '[[WP:ACID|Article Collaboration and Improvement Drive]] ' .. 'for the week of %s.' local date = validateDate('aciddate', args.aciddate) return string.format(blurb, date) end }, -- League of Copy Editors { id = 'LOCE', isActive = function (articleHistoryObj) return articleHistoryObj.args.loceNotAnActiveOption end, icon = 'LoCiconRevised.png', iconCaption = 'League of Copyeditors', iconSize = '25px', noticeBarIcon = true, text = 'This article, or a portion of it, was copyedited by the ' .. '[[WP:LoCE|League of Copyeditors]].' } }, ------------------------------------------------------------------------------- -- Notice bar icons ------------------------------------------------------------------------------- -- This table holds configuration tables for notice bar icons that don't appear -- as part of a row. Other notice bar icons are handled in the statuses, -- notices, actions, and collapsibleNotices tables. -- It accepts the following fields: -- isActive: a function that should return a truthy value if the notice should -- be displayed, and a falsy value if not. (Falsy values are false and nil, -- and truthy values are everything else.) The function takes an article -- history object as its first parameter. -- icon: the filename of the notice bar icon, minus the "File:" prefix. noticeBarIcons = { -- Peer review, or NA status { isActive = function (articleHistoryObj) local status = articleHistoryObj:getStatusId() -- @XXX: This is what the template does, but we should take into -- account peer review actions as well. return not status or status == 'PR' or status == 'NA' end, icon = 'Nuvola apps kedit.svg' }, -- Wikipedia 1.0 { isActive = function (articleHistoryObj) return articleHistoryObj.args['v1.0NotAnActiveOption'] end, icon = 'WP1 0 Icon.svg' } }, ------------------------------------------------------------------------------- -- Extra categories ------------------------------------------------------------------------------- -- This table contains categories that don't appear as part of a row. It is an -- array of functions; each function takes an article history object as input -- and must return an array of category objects as output. extraCategories = { -- Four award function (articleHistoryObj) local yesno = require('Module:Yesno') local ret = {} local isFour = yesno(articleHistoryObj.args.four) if isFour then ret[#ret + 1] = Category.new('Wikipedia four award articles') elseif isFour == false then ret[#ret + 1] = Category.new('Wikipedia articles rejected for Four awards') elseif articleHistoryObj:getStatusId() == 'FA' then local isDYK = false for _, obj in ipairs(articleHistoryObj:getCollapsibleNoticeObjects()) do if obj.id == 'DYK' then isDYK = true break end end if isDYK then for _, obj in ipairs(articleHistoryObj:getActionObjects()) do if obj.id == 'GAN' and obj.resultId == 'listed' then ret[#ret + 1] = Category.new('Possible Wikipedia four award articles') break end end end end return ret end, -- Deletion to Quality award function (articleHistoryObj) local ret = {} local status = articleHistoryObj:getStatusId() if status == 'FA' or status == 'FL' or status == 'GA' then local iAfd = 0 local hasAfd = false local actionObjects = articleHistoryObj:getActionObjects() for i, obj in ipairs(actionObjects) do if obj.id == 'AFD' then iAfd = i hasAfd = true break end end if hasAfd then local function hasNomination(id, result) for i = iAfd + 1, #actionObjects do local obj = actionObjects[i] if obj.id == id and obj.resultId == result then return true end end return false end if status == 'GA' and hasNomination('GAN', 'listed') or status == 'FL' and hasNomination('FLC', 'promoted') or status == 'FA' and hasNomination('FAC', 'promoted') then ret[#ret + 1] = Category.new('Deletion to Quality Award candidates') end end end return ret end, }, ------------------------------------------------------------------------------- -- Parameters ------------------------------------------------------------------------------- -- The parameter values used to generate the page actions. These are used as -- Lua patterns, so any of the magic characters *+-.^$%[] should be escaped -- with a preceding % symbol. actionParamPrefix = 'action', actionParamSuffixes = { [''] = 'code', date = 'date', link = 'link', result = 'resultCode', oldid = 'oldid' }, -- The parameter used to set the current status. currentStatusParam = 'currentstatus', ------------------------------------------------------------------------------- -- Other settings ------------------------------------------------------------------------------- -- If this number or fewer of collapsible rows are present (including actions -- and collapsible notices) they will not be collapsed. If this is set to the -- string "all", all rows will always be visible. Otherwise, the input must be -- a number. The default is three rows. uncollapsedRows = 3, -- The default size for icons. The default is 30px. defaultIconSize = '30px', -- The default size for status icons. The default is 50px. defaultStatusIconSize = '50px', -- The default size for status icons for multi status templates. The default is 30px. defaultMultiStatusIconSize = '30px', -- The default size for notice bar icons. The default is 15px. defaultNoticeBarIconSize = '15px', -- The default size for collapsible status icons. The default is 50px. defaultCollapsibleNoticeIconSize = '20px', ------------------------------------------------------------------------------- -- Messages ------------------------------------------------------------------------------- msg = { -- The heading for the collapsible table of actions if we are in the main -- namespace or the talk namespace. ['milestones-header'] = 'Article milestones', -- The heading for the collapsible table of actions if we are in a different -- namespace. -- $1 - the subject namespace name. ['milestones-header-other-ns'] = '$1 milestones', -- The milestones date header. ['milestones-date-header'] = 'Date', -- The milestones process header. ['milestones-process-header'] = 'Process', -- The milestones result header. ['milestones-result-header'] = 'Result', -- The format to display the action dates in. The syntax is the same as the -- #time parser function. ['action-date-format'] = 'F j, Y', -- The category to use if any errors are detected. ['error-category'] = 'Article history templates with errors', -- Define boilerplate text for error messages and warnings, both with and -- without help links. -- $1 - the error message -- $2 - a link to a help page and section for the error ['error-message-help'] = 'Error: $1 ([[$2|help]]).', ['error-message-nohelp'] = 'Error: $1.', ['warning-help'] = 'Warning: $1 ([[$2|help]]).', ['warning-nohelp'] = 'Warning: $1.', -- Error for row objects that should output notice bar icons but for which no -- icon values could be found. ['row-error-missing-icon'] = "notice bar icon config set to 'true' but no " .. 'image could be found', -- A help link for row-error-missing-icon ['row-error-missing-icon-help'] = 'Template:Article history#Missing icon', -- Error for action objects that aren't passed a code. -- $1 - the parameter name for the code ['action-error-no-code'] = "no action code found in the '$1' parameter; " .. "please add a code or remove other parameters starting with '$1'", -- A help link for action-error-no-code ['action-error-no-code-help'] = 'Template:Article history#Action codes', -- Error for action objects that are passed an invalid code. -- $1 - the code that the user input -- $2 - the parameter name for the code ['action-error-invalid-code'] = "invalid action code '$1' passed to the '$2' parameter", -- A help link for action-error-invalid-code ['action-error-invalid-code-help'] = 'Template:Article history#Action codes', -- Error for action objects with blank result parameters, where result -- parameters are required for the action's ID. -- $1 - the action ID -- $2 - the result parameter name ['action-error-blank-result'] = "the '$1' action requires a result code; " .. "please add a result code to parameter '$2'", -- A help link for action-error-blank-result ['action-error-blank-result-help'] = 'Template:Article history#Action results', -- Error for action objects with invalid result parameters. -- $1 - the result code that the user input -- $2 - the action ID -- $3 - the result parameter name ['action-error-invalid-result'] = "invalid result '$1' for action '$2' " .. "detected in parameter '$3'", -- A help link for action-error-invalid-result ['action-error-invalid-result-help'] = 'Template:Article history#Action results', -- Warning for action objects with invalid dates. -- $1 - the date input by the user -- $2 - the date parameter name ['action-warning-invalid-date'] = "invalid date '$1' detected in parameter '$2'", -- A help link for action-warning-invalid-date ['action-warning-invalid-date-help'] = 'Template:Article history#Invalid date', -- Error for action objects with no dates. -- $1 - the parameter number -- $2 - the date parameter name -- $3 - the action parameter name ['action-warning-no-date'] = "no date specified for action $1; " .. "please add a date to parameter '$2' or remove the other parameters " .. "beginning with '$3'", -- A help link for action-warning-no-date ['action-warning-no-date-help'] = 'Template:Article history#No date', -- The text to display in place of the action date if it is missing. ['action-date-missing'] = '?', -- Error for action objects with invalid oldids. -- $1 - the oldid input by the user -- $2 - the oldid parameter name ['action-warning-invalid-oldid'] = "invalid oldid '$1' detected in parameter '$2'; " .. "if an oldid is specified it must be a positive integer", -- A help link for action-warning-invalid-oldid ['action-warning-invalid-oldid-help'] = 'Template:Article history#Invalid oldid', -- Error for invalid current status codes. -- $1 - the code input by the user ['articlehistory-warning-invalid-status'] = "'$1' is not a valid status code", -- A help link for articlehistory-warning-invalid-status ['articlehistory-warning-invalid-status-help'] = 'Template:Article history#Invalid status', -- Warning for invocations that specify a current status without specifying any -- actions. ['articlehistory-warning-status-no-actions'] = "a current status was supplied " .. 'without any actions', -- A help link for articlehistory-warning-status-no-actions ['articlehistory-warning-status-no-actions-help'] = 'Template:Article history#No actions', -- The text to display the current status at the bottom of the collapsible -- table. -- $1 - the current status name ['status-blurb'] = "Current status: '''$1'''", -- The text to display at the bottom of the collapsible table if the current -- status is unknown. ['status-unknown'] = '?', } ------------------------------------------------------------------------------- -- CONFIG TABLE END ------------------------------------------------------------------------------- }