Module:Old AfD multi
local yesno = require('Module:Yesno')
 local mMessageBox = require('Module:Message box')
 local TEMPLATE_PAGE = 'Template:Old AfD multi'
 
 -------------------------------------------------------------------------------
 -- Helper functions
 -------------------------------------------------------------------------------
 
 local function exists(page)
 	local success, exists = pcall(function ()
 		local title = mw.title.new(page)
 		return title.exists
 	end)
 	return success and exists
 end
 
 local function getAfdPage(page)
 	return 'Wikipedia:Articles for deletion/' .. page
 end
 
 local function getVfdPage(page)
 	return 'Wikipedia:Votes for deletion/' .. page
 end
 
 local function makeWikilink(page, display)
 	display = display or 'discussion'
 	return string.format('[[%s|%s]]', page, display)
 end
 
 local function makeUrlLink(page, display)
 	display = display or 'discussion'
 	return string.format('[%s %s]', page, display)
 end
 
 -------------------------------------------------------------------------------
 -- OldAfdMulti class
 -------------------------------------------------------------------------------
 
 local OldAfdMulti = {}
 OldAfdMulti.__index = OldAfdMulti
 
 function OldAfdMulti.new(args)
 	local self = setmetatable({}, OldAfdMulti)
 	self.currentTitle = mw.title.getCurrentTitle()
 
 	-- Preprocess the row args for easier looping.
 	self.rowData = {}
 	for k, v in pairs(args) do
 		if type(k) == 'string' then
 			local prefix, num = k:match('^(.-)([1-9][0-9]*)$')
 			if prefix and num then
 				num = tonumber(num)
 				if prefix == 'result' or
 					prefix == 'date' or
 					prefix == 'page' or
 					prefix == 'link' or
 					prefix == 'caption' or
 					prefix == 'votepage'
 				then
 					self.rowData[num] = self.rowData[num] or {}
 					self.rowData[num][prefix] = v
 				end
 			end
 		end
 	end
 	-- Set aliases for parameters ending in &quot;1&quot;.
 	if self.rowData[1] then
 		self.rowData[1].result = self.rowData[1].result or args.result
 		self.rowData[1].date = self.rowData[1].date or args.date
 		self.rowData[1].page = self.rowData[1].page or args.page
 		self.rowData[1].votepage = self.rowData[1].votepage or args.votepage
 		self.rowData[1].link = self.rowData[1].link or args.link
 		self.rowData[1].caption = self.rowData[1].caption or args.caption
 	elseif args.result or
 		args.date or
 		args.page or
 		args.votepage or
 		args.link or
 		args.caption
 	then
 		self.rowData[1] = {
 			result = args.result,
 			date = args.date,
 			page = args.page,
 			votepage = args.votepage,
 			link = args.link,
 			caption = args.caption
 		}
 	end
 	-- Remove any gaps in the array we made.
 	local function compressSparseArray(t)
 		local ret, nums = {}, {}
 		for num, data in pairs(t) do
 			nums[#nums + 1] = num
 		end
 		table.sort(nums)
 		for i, num in ipairs(nums) do
 			ret[i] = t[num]
 		end
 		return ret
 	end
 	self.rowData = compressSparseArray(self.rowData)
 	-- Set aliases that apply to all of the data tables.
 	for i, data in ipairs(self.rowData) do
 		data.page = data.page or data.votepage
 		data.votepage = nil
 	end
 
 	-- Set collapsedness
 	self.collapse = tonumber(args.collapse)
 	if not self.collapse then
 		self.collapse = yesno(args.collapse)
 	end
 
 	-- Set other properties
 	self.isNumbered = yesno(args.numbered)
 	self.isSmall = yesno(args.small)
 	self.pageType = args.type or 'page'
 
 	return self
 end
 
 function OldAfdMulti:renderResult(result)
 	return result or &quot;'''Keep'''&quot;
 end
 
 function OldAfdMulti:renderDate(date)
 	if date then
 		return date
 	else
 		self.hasMissingDate = true
 		return string.format(
 			'&lt;sup&gt;%s[[%s|date missing]]%s&lt;/sup&gt;',
 			mw.text.nowiki('['),
 			TEMPLATE_PAGE,
 			mw.text.nowiki(']')
 		)
 	end
 end
 
 function OldAfdMulti:renderPageText(linkFunc, page, caption)
 	return string.format(', see %s.', linkFunc(page, caption))
 end
 
 function OldAfdMulti:renderRow(result, date, link)
 	local result = self:renderResult(result)
 	local date = self:renderDate(date)
 	if link then
 		return string.format('%s, %s, see %s.', result, date, link)
 	else
 		return string.format('%s, %s', result, date)
 	end
 end
 
 function OldAfdMulti:renderFirstRow(data)
 	local link
 	if data.link then
 		link = makeUrlLink(data.link, data.caption)
 	else
 		local page = data.page or self.currentTitle.text
 		link = makeWikilink(getAfdPage(page), data.caption)
 	end
 	return self:renderRow(data.result, data.date, link)
 end
 
 function OldAfdMulti:renderSubsequentRow(data)
 	local link
 	if data.page then
 		link = makeWikilink(getAfdPage(data.page), data.caption)
 	elseif data.link then
 		link = makeUrlLink(data.link, data.caption)
 	end
 	return self:renderRow(data.result, data.date, link)
 end
 
 function OldAfdMulti:renderRows()
 	local root = mw.html.create()
 	local nRows = #self.rowData
 	local i = nRows
 
 	local nCollapsedRows
 	if type(self.collapse) == 'number' then
 		nCollapsedRows = self.collapse
 	elseif self.collapse then
 		nCollapsedRows = nRows
 	else
 		nCollapsedRows = 0
 	end
 	local hasNormalRows = nRows - nCollapsedRows &gt; 0
 
 	local function makeList(isCollapsed, header)
 		local tableRoot = root:tag('table')
 		tableRoot
 			:addClass(isCollapsed and 'collapsible collapsed' or nil)
 			:css('width', '100%')
 			:css('background-color', '#f8eaba')
 		if header then
 			tableRoot
 				:tag('tr')
 					:tag('th')
 						:wikitext(header)
 		end
 		return tableRoot
 			:tag('tr')
 				:tag('td')
 					:tag(self.isNumbered and 'ol' or 'ul')
 	end
 
 	local function renderRow(html, method, data)
 		html
 			:tag('li')
 				:attr('value', self.isNumbered and i or nil)
 				:wikitext(self[method](self, data))
 	end
 
 	-- Render normal rows
 	if hasNormalRows then
 		local normalList = makeList(false)
 		while i &gt; 1 and i &gt; nCollapsedRows do
 			renderRow(normalList, 'renderSubsequentRow', self.rowData[i])
 			i = i - 1
 		end
 		if i == 1 and i &gt; nCollapsedRows then
 			renderRow(normalList, 'renderFirstRow', self.rowData[i])
 			i = i - 1
 		end
 	end
 
 	-- Render collapsed rows
 	if nCollapsedRows &gt; 0 then
 		local header
 		if hasNormalRows then
 			header = 'Older deletion discussions:'
 		elseif nRows &gt; 1 then
 			header = 'Deletion discussions:'
 		else
 			header = 'Deletion discussion:'
 		end
 		local collapsedList = makeList(true, header)
 		while i &gt; 1 do
 			renderRow(collapsedList, 'renderSubsequentRow', self.rowData[i])
 			i = i - 1
 		end
 		renderRow(collapsedList, 'renderFirstRow', self.rowData[i])
 	end
 
 	return tostring(root)
 end
 
 function OldAfdMulti:renderFirstRowOnly()
 	local data = self.rowData[1] or {}
 	local caption = data.caption or 'the discussion'
 	local link
 	if data.link then
 		link = makeUrlLink(data.link, caption)
 	else
 		local page = data.page or self.currentTitle.text
 		if exists(getAfdPage(page)) then
 			link = makeWikilink(getAfdPage(page), caption)
 		elseif exists(getVfdPage(page)) then
 			link = makeWikilink(getVfdPage(page), caption)
 		else
 			link = caption -- Make this an error?
 		end
 	end
 	local result = self:renderResult(data.result or &quot;'''keep'''&quot;)
 	return string.format(
 		'The result of %s was %s.',
 		link, result
 	)
 end
 
 function OldAfdMulti:renderBannerText()
 	local nRows = #self.rowData
 	local ret = {}
 	if nRows &lt; 1 or not self.rowData[1].date then
 		ret[#ret + 1] = string.format(
 			'This %s was previously nominated for [[Wikipedia:Deletion policy|deletion]].',
 			self.pageType
 		)
 	elseif nRows == 1 and self.rowData[1].date then
 		ret[#ret + 1] = string.format(
 			'This %s was nominated for [[Wikipedia:Deletion policy|deletion]] on %s.',
 			self.pageType,
 			self.rowData[1].date
 		)
 	else
 		ret[#ret + 1] = string.format(
 			'This %s was nominated for [[Wikipedia:Deletion policy|deletion]].',
 			self.pageType
 		)
 	end
 	if nRows &gt; 1 then
 		ret[#ret + 1] = ' '
 		if self.isSmall then
 			ret[#ret + 1] = 'Review prior discussions if considering re-nomination:'
 		else
 			ret[#ret + 1] = 'Please review the prior discussions if you are considering re-nomination:'
 		end
 		ret[#ret + 1] = '\n'
 		ret[#ret + 1] = self:renderRows()
 	else
 		ret[#ret + 1] = ' '
 		ret[#ret + 1] = self:renderFirstRowOnly()
 	end
 	return table.concat(ret)
 end
 
 function OldAfdMulti:renderBanner()
 	return mMessageBox.main('tmbox', {
 		small = self.isSmall,
 		type = 'notice',
 		image = '[[File:Clipboard.svg|35px|Articles for deletion]]',
 		smallimage = 'none',
 		text = self:renderBannerText()
 	})
 end
 
 function OldAfdMulti:renderTrackingCategories()
 	local ret = {}
 	if self.hasMissingDate and self.currentTitle.isTalkPage then
 		ret[#ret + 1] = '[[Category:Old AfD multi templates with errors]]'
 	end
 	return table.concat(ret)
 end
 
 function OldAfdMulti:__tostring()
 	return self:renderBanner() .. self:renderTrackingCategories()
 end
 
 -------------------------------------------------------------------------------
 -- Exports
 -------------------------------------------------------------------------------
 
 local p = {}
 
 function p._main(args)
 	local afd = OldAfdMulti.new(args)
 	return tostring(afd)
 end
 
 function p.main(frame)
 	local args = require('Module:Arguments').getArgs(frame, {
 		wrappers = TEMPLATE_PAGE
 	})
 	return p._main(args)
 end