Module:Article history/config: Difference between revisions

Content deleted Content added
set PR to "reviewed" if the result parameter is absent
Update featured portal wording per request
 
(118 intermediate revisions by 17 users not shown)
Line 3:
-------------------------------------------------------------------------------
 
local lang = mw.language.getContentLanguage()
local Category = require('Module:Article history/Category')
 
Line 9 ⟶ 10:
-------------------------------------------------------------------------------
 
-- 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
Line 16 ⟶ 27:
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)
Line 27 ⟶ 41:
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 was archived. 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 was archived. " ..
"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')
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 oppose 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 was archived."
},
FPO = {
id = 'FPO',
name = 'Featured portal',
icon = 'Linecons big-star.svg',
text = "This portal was '''[[Wikipedia:Featured portal candidates/Portal:$2|identified]]''' " ..
"as a [[Wikipedia:Featured portals|featured portal]] " ..
"before the [[Wikipedia:Village pump (proposals)/Archive 138#RfC " ..
'about marking the Featured portals process as "historical"|process ended in 2017]].',
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."
},
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 = {
Line 54 ⟶ 1,122:
aliases = {'fail', 'failed'}
}
},
validStatuses = {
FFAC = true,
FA = true,
FFA = true
}
},
Line 81 ⟶ 1,144:
aliases = {'merge'}
}
},
validStatuses = {
FA = true,
FFA = true
},
categories = function (articleHistoryObj, actionObj)
Line 112 ⟶ 1,171:
aliases = {'pass', 'promoted', 'nom'}
}
},
validStatuses = {
}
},
Line 130 ⟶ 1,187:
aliases = {'fail', 'failed', 'remove', 'removed', 'demoted'}
}
},
validStatuses = {
FA = true,
FFAC = true
},
categories = function (articleHistoryObj, actionObj)
Line 151 ⟶ 1,204:
results = {
promoted = {
id = 'promoted',
text = 'Promoted',
aliases = {'pass', 'passed'}
},
['not promoted'] = {
id = 'not promoted',
text = 'Not promoted',
aliases = {'fail', 'failed'}
}
},
validStatuses = {
FFLC = true,
FL = true,
FFL = true
}
},
Line 184 ⟶ 1,234:
aliases = {'merge'}
}
},
validStatuses = {
FL = true,
FFL = true
},
categories = function (articleHistoryObj, actionObj)
Line 221 ⟶ 1,267:
aliases = {'fail', 'failed'}
}
},
validStatuses = false, -- Any status
},
FTR = {
Line 243 ⟶ 1,288:
aliases = {'merge'}
}
},
validStatuses = false, -- Any status
},
FPOC = {
Line 260 ⟶ 1,304:
aliases = {'fail', 'failed'}
}
},
validStatuses = {
FFPOC = true,
FPO = true,
FFPO = true
}
},
Line 286 ⟶ 1,325:
aliases = {'merge'}
}
},
validStatuses = {
FPO = true,
FFPO = true
}
},
Line 307 ⟶ 1,342:
aliases = {'fail', 'failed', 'not promoted'}
}
},
validStatuses = {
FGAN = true,
GA = true,
DGA = true,
FFAC = true,
FA = true,
FFA = true
},
categories = function (articleHistoryObj, actionObj)
Line 355 ⟶ 1,382:
text = 'Not listed'
}
},
validStatuses = {
GA = true,
DGA = true,
FFAC = true,
FA = true,
FFA = true
},
categories = function (articleHistoryObj, actionObj)
Line 392 ⟶ 1,412:
aliases = {'fail', 'failed'}
}
},
validStatuses = false
},
GTR = {
Line 414 ⟶ 1,433:
aliases = {'merge'}
}
},
validStatuses = false
},
PR = {
Line 431 ⟶ 1,449:
}
},
validStatuses = false,
categories = {'Old requests for peer review'}
},
Line 493 ⟶ 1,510:
}
},
categories = function (articleHistoryObj, actionObj)
validStatuses = false
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 = {
Line 523 ⟶ 1,547:
text = 'Demoted',
aliases = {'demote'}
},
},
validStatuses = false
},
AFD = {
Line 569 ⟶ 1,592:
text = 'Renamed',
aliases = {'rename', 'move', 'moved'}
},
},
validStatuses = false
},
MFD = {
id = 'MFD',
name = 'MiscellaneaMiscellany for deletion',
results = {
kept = {
Line 615 ⟶ 1,637:
text = 'Renamed',
aliases = {'rename', 'move', 'moved'}
},
},
validStatuses = false
},
TFD = {
Line 657 ⟶ 1,678:
},
renamed = {
id = 'renamed',
text = 'Renamed',
aliases = {'rename', 'move', 'moved'}
},
},
validStatuses = false
},
CSD = {
Line 675 ⟶ 1,696:
id = 'deleted',
text = 'Deleted',
aliases = {'delete', 'speedily deleted', 'speedy delete'}
},
merged = {
id = 'merged',
text = 'Merged',
aliases = {'merge'}
},
['no consensus'] = {
id = 'no consensus',
text = 'No consensus'
},
['speedily kept'] = {
Line 690 ⟶ 1,702:
text = 'Speedily kept',
aliases = {'speedy keep'}
},
['speedily deleted'] = {
id = 'speedily deleted',
text = 'Speedily deleted',
aliases = {'speedy delete'}
},
redirected = {
Line 700 ⟶ 1,707:
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 = {
Line 705 ⟶ 1,722:
text = 'Renamed',
aliases = {'rename', 'move', 'moved'}
},
},
validStatuses = false
},
PROD = {
Line 722 ⟶ 1,738:
text = 'Deleted',
aliases = {'delete'}
},
merged = {
id = 'merged',
text = 'Merged',
aliases = {'merge'}
},
['no consensus'] = {
id = 'no consensus',
text = 'No consensus'
},
['speedily kept'] = {
id = 'nospeedily consensuskept',
text = 'Speedily kept',
aliases = {'speedy keep'}
Line 746 ⟶ 1,753:
text = 'Redirected',
aliases = {'redirect'}
},
afd = {
id = 'afd',
text = 'Sent to [[WP:AFD|articles for deletion]]',
aliases = {'afded'}
},
renamed = {
Line 751 ⟶ 1,763:
text = 'Renamed',
aliases = {'rename', 'move', 'moved'}
},
},
validStatuses = false
},
DRV = {
Line 773 ⟶ 1,784:
text = 'Overturned',
aliases = {'overturn'}
},
restored = {
id = 'restored',
text = 'Restored',
aliases = {'restore'}
},
['no consensus'] = {
Line 778 ⟶ 1,794:
text = 'No consensus'
}
},
validStatuses = false
}
},
 
-------------------------------------------------------------------------------
-- Collapsible notices
-- Statuses
-- Configuration for possible current statuses of the article.
-------------------------------------------------------------------------------
 
-- The statusescollapsibleNotices table contains validconfiguration statuses.tables for notices that
-- go in the collapsible part of the template, underneath the actions.
-- Each status can have the following fields:
-- Each configuration table can have the following fields:
--
-- id: the main ID for the statusnotice. 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.
-- isActive: a function that should return a truthy value if the notice should
-- icon: The status icon.
-- 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
-- defaultStatusIconSizedefaultIconSize.
-- iconSmallSizetext: The iconnotice sizetext. ifThis wemay are outputtingbe a smallstring templateor a function. TheIf it is a
-- function, it takes an article history object as the first parameter, and
-- default is defined in defaultSmallStatusIconSize.
-- the current collapsible notice object as the second parameter, and should
-- text: The status text. This may be a string or a function. If it is a
-- return the text string.
-- function, it takes an article history object as input, and should return
-- categories: The categories set by the notice. This may be an array of
-- the text string. If it is a string, it can have the following parameters:
-- category names, or a function. If it is a function, it takes an article
-- $1 - The full page name of the article or subject page
-- $2history -object Theas pagethe namefirst withoutparameter, and the namespacecurrent collapsible namenotice
-- object as the second parameter, and should return an array of category
-- categories: An array of categories used by the status.
-- 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 = {
statuses = {
FA-- = {DYK
{
id = 'FA',
nameid = 'Featured articleDYK',
icon = 'FeaturedSymbol article starquestion.svg',
iconCaption = 'Did You Know',
text = function (articleHistoryObj)
noticeBarIcon = true,
local articlePage = articleHistoryObj.currentTitle.subjectPageTitle.prefixedText
isActive = function (articleHistoryObj)
local actions = articleHistoryObj:getActionObjects()
return isActiveDatedObject(articleHistoryObj, 'dyk')
local link
end,
for i = #actions, 1, -1 do
makeData = function (articleHistoryObj)
local actionObj = actions[i]
return makeDateData(articleHistoryObj, 'dyk', {'entry', 'nom', 'ignoreerror'})
if actionObj.id == 'FAC' then
end,
link = actionObj.link
text = function (articleHistoryObj, collapsibleNoticeObj)
break
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
linklocal fact = link'fact orfrom 'Wikipedia:Featuredthis article candidates/' .. articlePage
local nomPage = data[1].nom or ('Template:Did you know nominations/' .. articleHistoryObj.currentTitle.text)
local text = "'''%s''' is a [[Wikipedia:Featured articles|featured article]]; " ..
if titleExists(nomPage) then
"it (or a previous version of it) has been '''''[[%s|identified]]''''' " ..
fact = '[[' .. nomPage .. '|' .. fact .. ']]'
"as one of the best articles produced by the [[Wikipedia:Wikipedians|Wikipedia community]]. " ..
end
"Even so, if you can update or improve it, [[Wikipedia:Be bold|please do so]]."
local blurb = "A " .. fact .. " appeared on " ..
return string.format(text, articlePage, link)
"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)
categories = {'Wikipedia featured articles'}
local data = collapsibleNoticeObj:getData(articleHistoryObj)
},
if not data then
FFA = {
return nil
id = 'FFA',
end
name = 'Former featured article',
local ctext = {}
icon = 'Featured article star - cross.svg',
if #data == 1 and data[1].entry then
iconSize = '48px',
ctext[#ctext + 1] = string.format(
text = "'''$1''' is a [[Wikipedia:Former featured articles|former featured article]]. " ..
"The text of the entry was: ''Did you know %s''",
"Please see the links under Article milestones below for its original nomination page " ..
data[1].entry
"(for older articles, check [[Wikipedia:Featured article candidates/Archived nominations/Index|the nomination archive]]) " ..
)
"and why it was removed.",
else
categories = {'Wikipedia former featured articles'}
local entries = {}
},
local lastEntryDate
FFAC = {
for _, t in ipairs(data) do
id = 'FFAC',
entries[#entries + 1] = t.entry
name = 'Former featured article candidate',
lastEntryDate = t.date
aliases = {'FACFAILED'},
end
icon = 'Cscr-former.svg',
if #entries == 1 then
text = "'''$1''' is a former [[Wikipedia:Featured article candidates|featured article candidate]]. " ..
ctext[#ctext + 1] = string.format(
"Please view the links under Article milestones below to see why " ..
"The text of the entry for %s was: ''Did you know %s''",
"the nomination failed. For older candidates, please check the " ..
lastEntryDate, entries[1]
"[[Wikipedia:Featured article candidates/Archived nominations/Index|archive]]."
)
},
elseif #entries > 1 then
FL = {
ctext[#ctext + 1] = 'The text of the entries was:\n'
id = 'FL',
local list = mw.html.create('ul')
name = 'Featured list',
for _, t in ipairs(data) do
icon = 'Featured article star.svg',
if t.entry then
iconSize = '48px',
list:tag('li'):wikitext(string.format(
text = function (articleHistoryObj)
"%s: ''Did you know %s''",
local articlePage = articleHistoryObj.currentTitle.subjectPageTitle.prefixedText
t.date, t.entry
local actions = articleHistoryObj:getActionObjects()
local link ))
end
for i = #actions, 1, -1 do
end
local actionObj = actions[i]
ctext[#ctext + 1] = tostring(list)
if actionObj.id == 'FLC' then
link = actionObj.link
break
end
end
if #ctext > 0 then
link = link or 'Wikipedia:Featured list candidates/' .. articlePage
return table.concat(ctext)
local text = "'''%s''' is a [[Wikipedia:Featured lists|featured list]], " ..
else
"which means it has been '''''[[%s|identified]]''''' as one of the best " ..
return nil
"[[Wikipedia:Lists|lists]] produced by the [[Wikipedia:Wikipedians|Wikipedia community]]. " ..
end
"If you can update or improve it, [[Wikipedia:Be bold|please do so]]."
return string.format(text, articlePage, link)
end,
categories = {'Wikipediafunction featured(articleHistoryObj, lists'}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
},
 
FFL = {
-- ITN
id = 'FFL',
{
name = 'Former featured list',
iconid = 'Cscr-featured-strike.svgITN',
isActive = function (articleHistoryObj)
text = "'''$1''' is a [[Wikipedia:Former featured lists|former featured list]]. " ..
return isActiveDatedObject(articleHistoryObj, 'itn')
"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 list|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',
isDouble = true,
statuses = {'FFA', 'GA'}
},
GA = {
id = 'GA',
name = 'Good article',
icon = 'Symbol support vote.svg',
iconSize = '40px',
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,
categoriesmakeData = function (articleHistoryObj)
return makeDateData(articleHistoryObj, 'itn', {'link'})
local ret = {}
end,
local title = articleHistoryObj.currentTitle
icon = 'Globe current.svg',
if title.namespace == 1 then
iconCaption = 'In the news',
ret[#ret + 1] = Category.new('Wikipedia good articles')
noticeBarIcon = true,
ret[#ret + 1] = Category.new('Wikipedia CD Selection-GAs')
noticeBarIconSize = '20px',
ret[#ret + 1] = Category.new('GA-Class Good articles')
local topictext = getGoodArticleTopicfunction (articleHistoryObj.args.topic, collapsibleNoticeObj)
local data = collapsibleNoticeObj:getData(articleHistoryObj)
if topic then
if not data then
ret[#ret + 1] = Category.new(
return nil
topic .. ' good articles',
end
title.text
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
else
ret[#ret + 1]date.link = Categorystring.newformat(
'Wikipedia:ITN archives/%d/%s',
'Good articles without topic parameter',
titlet.textyear,
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
returnlocal retintro
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
},
 
FGAN = {
-- On This Day
id = 'FGAN',
{
name = 'Former good article nominee',
aliasesid = {'FAILEDGAOTD'},
isActive = function (articleHistoryObj)
icon = 'Symbol unsupport vote.svg',
text = function return isActiveDatedObject(articleHistoryObj, 'otd')
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 are 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,
makeData = function (articleHistoryObj)
categories = {'Former good article nominees'}
return makeDateData(articleHistoryObj, 'otd', {'link', 'oldid'})
},
-- TODO: remove 'link' after it is no longer needed for tracking
DGA = {
id = 'DGA',
name = 'Former good article',
aliases = {'DELISTEDGA'},
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 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,
categoriesicon = {'DelistedNuvola goodapps articlesdate.svg'},
iconCaption = 'On this day...',
},
noticeBarIcon = true,
FFT = {
idnoticeBarIconSize = 'FFT20px',
text = function (articleHistoryObj, collapsibleNoticeObj)
name = 'Part of former featured topic',
local data = collapsibleNoticeObj:getData(articleHistoryObj)
icon = 'Cscr-featured-strike.svg',
if not data then
iconCaption = 'Former featured topic',
return nil
text = "This article is part of a " ..
end
"''[[Wikipedia:Former featured topics|former featured topic]]'' series. " ..
local dates = {}
"If it has improved again to " ..
for _, t in ipairs(data) do
"[[Wikipedia:Featured topic criteria|featured topic standard]], " ..
local date = {}
"you may [[Wikipedia:Featured topic candidates|renominate]] " ..
date.date = t.date
"the topic to become a [[Wikipedia:Featured topic|featured topic]]."
date.link = t.link
},
if t.oldid then
FFTC = {
-- TODO: Move this inside the main module
id = 'FFTC',
local oldid = tonumber(t.oldid)
name = 'Former featured topic candidate',
if oldid and
icon = 'Cscr-former.svg',
math.floor(oldid) == oldid and
text = "This article is part of a ''former'' " ..
oldid > 0 and
"[[Wikipedia:Featured topic candidates|featured topic candidate]]. " ..
oldid < math.huge
"Please view the links under Article milestones below to see why " ..
then
"the nomination failed."
-- If the oldid is valid, it takes precedence over
},
-- explicit links.
FPO = {
date.link = 'Special:PermaLink/' .. t.oldid
id = 'FPO',
else
name = 'Featured portal',
collapsibleNoticeObj:addWarning(
icon = 'Cscr-former.svg',
string.format(
text = "The '''$2 Portal''' is a [[Wikipedia:Featured portals|featured portal]], " ..
"whichinvalid meansoldid it'%s' hasdetected beenin parameter '%s'; " ..
"if an oldid is specified it must be a positive integer",
"'''''[[Wikipedia:Featured portal candidates/Portal:$2|identified]]''''' " ..
t.oldid,
"as one of the best portals on [[Wikipedia]]. " ..
t.argPrefix .. 'oldid'
"If you see a way this portal can be updated or improved without " ..
),
"compromising previous work, please feel free to contribute.",
'Template:Article history#Invalid oldid'
categories = function (articleHistoryObj)
)
return {Category.new(
end
'Wikipedia featured portals',
end
articleHistoryObj.currentTitle.text
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
},
 
FFPO = {
-- Article Collaboration and Improvement Drive
id = 'FFPO',
{
name = 'Former featured portal',
id = 'ACID',
icon = 'Featured article star - cross.svg',
isActive = function (articleHistoryObj)
text = "This portal is a [[Wikipedia:Former featured portals|former featured portal]]. " ..
return articleHistoryObj.args.aciddate
"Please see the links under Portal milestones below for its " ..
end,
"original nomination page and why it was removed.",
icon = 'Article Collaboration and Improvement Drive.svg',
categories = function (articleHistoryObj)
iconCaption = 'Article Collaboration and Improvement Drive',
return {Category.new(
noticeBarIcon = true,
'Wikipedia former featured portals',
noticeBarIconSize = '20px',
articleHistoryObj.currentTitle.text
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
},
 
FFPOC = {
-- League of Copy Editors
id = 'FFPOC',
{
name = 'Former featured portal candidate',
iconid = 'Cscr-former.svgLOCE',
isActive = function (articleHistoryObj)
text = "This portal is a '''''former''''' " ..
return articleHistoryObj.args.loceNotAnActiveOption
"[[Wikipedia:Featured portal candidates|featured portal candidate]]. " ..
end,
"Please see the links under Portal milestones below for its " ..
icon = 'LoCiconRevised.png',
"original nomination page and why the nomination failed.",
iconCaption = 'League of Copyeditors',
categories = function (articleHistoryObj)
iconSize = '25px',
return {Category.new(
noticeBarIcon = true,
'Wikipedia featured portal candidates (contested)',
text = 'This article, or a portion of it, was copyedited by the ' ..
articleHistoryObj.currentTitle.text
'[[WP:LoCE|League of Copyeditors]].'
)}
end
},
PR = {
-- Peer review is a valid current status, but it doesn't trigger a
-- header row.
id = 'PR',
name = 'Peer reviewed'
}
},
 
-- The following are statuses that
nullStatuses = {
PR = true
},
 
invalidStatuses = {
FAC = {
id = 'FAC'
},
FAR = {
id = 'FAR'
},
STUB = {
id = 'STUB',
aliases = {'START', 'B', 'A'}
},
NA = {
id = 'NA',
aliases = {'PR', ''}
},
},
 
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 statuses = articleHistoryObj.cfg.statuses
local statusCode = articleHistoryObj.args.currentstatus
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
-- @TODO: Error
elseif statusId == 'GA' then
statusId = 'FFA/GA'
elseif statusId ~= 'FFA' then
-- @TODO: Error -
end
end
end
 
return statusId
end,
 
-------------------------------------------------------------------------------
-- Notice bar icons
-- Notices
-------------------------------------------------------------------------------
 
-- This table holds configuration tables for notice bar icons that don't appear
notices = {
-- 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)
param = 'ftname'
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
-- Collapsible notices
-------------------------------------------------------------------------------
 
-- This table contains categories that don't appear as part of a row. It is an
collapsibleNotices = {
-- 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,
},
 
Line 1,148 ⟶ 2,259:
oldid = 'oldid'
},
 
-- The parameter used to set the current status.
currentStatusParam = 'currentstatus',
 
-------------------------------------------------------------------------------
Line 1,161 ⟶ 2,275:
-- The default size for icons. The default is 30px.
defaultIconSize = '30px',
 
-- The default size for icons for small templates. The default is 15px.
defaultSmallIconSize = '15px',
 
-- The default size for status icons. The default is 50px.
defaultStatusIconSize = '50px',
 
-- The default size for status icons for smallmulti status templates. The default is 30px.
defaultSmallStatusIconSizedefaultMultiStatusIconSize = '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',
 
-------------------------------------------------------------------------------
Line 1,197 ⟶ 2,311:
-- The milestones result header.
['milestones-result-header'] = 'Result',
 
-- The text displayed when the current status is unknown.
['status-unknown'] = '?',
 
-- The format to display the action dates in. The syntax is the same as the
Line 1,206 ⟶ 2,317:
 
-- The category to use if any errors are detected.
['error-category'] = 'ArticleHistoryArticle 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.
Line 1,220 ⟶ 2,342:
 
-- A help link for action-error-no-code
['action-error-no-code-help'] = 'Template:Article history#ErrorsAction codes',
 
-- Error for action objects that are passed an invalid code.
Line 1,228 ⟶ 2,350:
 
-- A help link for action-error-invalid-code
['action-error-invalid-code-help'] = 'Template:Article history#ErrorsAction codes',
 
-- Error for action objects with blank result parameters, where result
Line 1,238 ⟶ 2,360:
 
-- A help link for action-error-blank-result
['action-error-blank-result-help'] = 'Template:Article history#ErrorsAction results',
 
-- Error for action objects with invalid result parameters.
Line 1,248 ⟶ 2,370:
 
-- A help link for action-error-invalid-result
['action-error-invalid-result-help'] = 'Template:Article history#ErrorsAction results',
 
-- ErrorWarning for action objects with invalid dates.
-- $1 - the date input by the user
-- $2 - the date parameter name
['action-errorwarning-invalid-date'] = "invalid date '$1' detected in parameter '$2'",
 
-- A help link for action-errorwarning-invalid-date
['action-errorwarning-invalid-date-help'] = 'Template:Article history#ErrorsInvalid date',
 
-- Error for action objects with no dates.
-- $1 - the parameter number
-- $2 - the date parameter name
-- $3 - the action parameter name
['action-error-no-date'] = "no date specified for action $1; " ..
"please add a ['action-warning-no-date to parameter '$2'] or= remove"no thedate other parametersspecified for action $1; ", ..
"please add a date to parameter '$2' or remove the other parameters " ..
"beginning with '$3'",
 
-- A help link for action-errorwarning-no-date
['action-errorwarning-no-date-help'] = 'Template:Article history#ErrorsNo date',
 
-- The text to display in place of the action date if it is missing.
Line 1,273 ⟶ 2,397:
-- $1 - the oldid input by the user
-- $2 - the oldid parameter name
['action-errorwarning-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-errorwarning-invalid-oldid
['action-errorwarning-invalid-oldid-help'] = 'Template:Article history#ErrorsInvalid 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'] = '?',
 
}