Difference between revisions of "Module:Limitation status list"
(endDate not used anywhere) |
(Don't show the navigation menu, if prev and next are both empty) |
||
Line 63: | Line 63: | ||
function List:addCards(status, listInput) | function List:addCards(status, listInput) | ||
-- Exit early if there is no input | -- Exit early if there is no input | ||
− | if ( | + | if not isFilled(listInput) then return end |
-- Split the input by new line and loop through each line | -- Split the input by new line and loop through each line | ||
Line 151: | Line 151: | ||
-- @return string | -- @return string | ||
function List:renderNavigation() | function List:renderNavigation() | ||
+ | -- If prev and next are both empty, don't show a navigation menu | ||
+ | if (not isFilled(self.prev) and not isFilled(self.next)) then | ||
+ | return '' | ||
+ | end | ||
+ | |||
local currText = self:pageNameToShortName(self.name) | local currText = self:pageNameToShortName(self.name) | ||
local prevText = self.prev and ('← [[' .. self.prev .. '|' .. self:pageNameToShortName(self.prev) .. ']]') or ' ' | local prevText = self.prev and ('← [[' .. self.prev .. '|' .. self:pageNameToShortName(self.prev) .. ']]') or ' ' | ||
Line 216: | Line 221: | ||
return tostring(heading) .. tostring(list) | return tostring(heading) .. tostring(list) | ||
+ | end | ||
+ | |||
+ | -- Check if something has been filled out | ||
+ | -- i.e. check that it's neither `nil` nor empty string | ||
+ | -- @param value mixed | ||
+ | -- @return bool | ||
+ | function isFilled(value) | ||
+ | return value ~= nil and value ~= '' | ||
end | end | ||
return List | return List |
Revision as of 15:47, 4 December 2023
Module:Limitation status list is implemented by Template:Limitation list
-- Shell object for the list itself
local List = {
name = nil,
medium = nil,
locality = nil,
startDate = nil,
prev = nil,
next = nil,
cards = {}
}
-- Shell object for a card in the list
local ListCard = {
link = nil,
name = nil,
cardType = nil,
status = nil,
prevStatus = nil,
note = nil
}
-- Main function that gets invoked
-- Create a new list from the user input, then render it
function List.list(frame)
-- Get the template parameters
local args = frame:getParent().args
local l = List:new(args)
return l:render()
end
-- Create a new instance of a list
-- @param args table
-- @return List
function List:new(args)
local l = mw.clone(List)
l:setData(args or {})
return l
end
-- Main function for setting data for the list
-- @param args table - data from the user input
function List:setData(args)
self.name = args.name or mw.title.getCurrentTitle().text
self.medium = args.medium
self.locality = args.locality
self.startDate = args.start_date
self.prev = args.prev
self.next = args.next
self.cards = {}
self:addCards('Forbidden', args.forbidden)
self:addCards('Limited', args.limited)
self:addCards('Semi-Limited', args.semi_limited)
self:addCards('Unlimited', args.no_longer_on_list)
end
-- Add cards based on user input
-- @param status string
-- @param listInput string
function List:addCards(status, listInput)
-- Exit early if there is no input
if not isFilled(listInput) then return end
-- Split the input by new line and loop through each line
local listItems = mw.text.split(listInput, '\n')
for _, cardInput in pairs(listItems) do
-- Split the line input by semi colon and get data from each piece
local cardInputData = mw.text.split(cardInput, '%s*;%s*')
local link = cardInputData[1]
local prevStatus = cardInputData[2]
-- Look up data for the card
local cardData = self:lookupCardData(link)
-- Create a new card object and populate it
local card = mw.clone(ListCard)
card.link = link
card.name = cardData.name
card.cardType = cardData.cardType
card.status = status
card.prevStatus = cardInputData[2]
-- Add the card to the list
table.insert(self.cards, card)
end
end
function List:setSmwData()
mw.smw.set({
['Effective date'] = self.startDate,
['Medium'] = self.medium,
['Release'] = self.medium,
['Locality'] = self.locality,
['Page type'] = 'Status list'
})
for _, card in pairs(self.cards) do
mw.smw.subobject({
'List contains = ' .. card.link,
'Status = ' .. card.status,
})
end
end
-- Find data on a card by suppyling its name
function List:lookupCardData(pageName)
local cardData = mw.smw.ask{
'[[' .. pageName .. ']]',
'?English name = name',
'?Card type# = cardType',
mainlabel = '-'
}
return cardData and cardData[1] or {}
end
-- Filter a list's `cards` attribute by a status
-- @return table
function List:getCardsByStatus(status)
-- New array to contain cards with just the specified status
local filteredCards = {}
-- Loop through the list of all cards
for _, card in pairs(self.cards) do
-- If the card has the specified status, add it to the new array
if (card.status == status) then
table.insert(filteredCards, card)
end
end
return filteredCards
end
-- Render the overall output
-- @return string
function List:render()
local output = ''
output = output .. self:renderNavigation()
output = output .. self:renderStatusList('Forbidden')
output = output .. self:renderStatusList('Limited')
output = output .. self:renderStatusList('Semi-Limited')
output = output .. self:renderStatusList('Unlimited', 'No longer on list')
return output
end
-- Render the navigation section
-- @return string
function List:renderNavigation()
-- If prev and next are both empty, don't show a navigation menu
if (not isFilled(self.prev) and not isFilled(self.next)) then
return ''
end
local currText = self:pageNameToShortName(self.name)
local prevText = self.prev and ('← [[' .. self.prev .. '|' .. self:pageNameToShortName(self.prev) .. ']]') or ' '
local nextText = self.next and ('[[' .. self.prev .. '|' .. self:pageNameToShortName(self.next) .. ']] →') or ' '
local output = '<div style="border: 1px solid #aaa; display: flex; margin-bottom: .5em;">'
output = output .. '<div style="flex: 1; padding: .25em; text-align: left;">' .. prevText .. '</div>'
output = output .. '<div style="flex: 1; padding: .25em; text-align: center;">' .. currText .. '</div>'
output = output .. '<div style="flex: 1; padding: .25em; text-align: right;">' .. nextText .. '</div>'
output = output .. '</div>'
return output
end
-- Convert a page name to a short name
-- e.g. "March 2020 Lists (Duel Links)" -> "March 2020 Lists"
-- e.g. "OCG April 2014 Lists" -> "April 2014 Lists"
-- @param pageName string
-- @return string
function List:pageNameToShortName(pageName)
-- Strip out disambiguation text
local shortName = mw.text.split(pageName, ' %(')[1]
-- Remove mention of the medium
shortName = shortName:gsub(self.medium, '')
-- Clear any leading/trailing spaces
return mw.text.trim(shortName)
end
-- Render a section with a list fora given status
-- @param status string
-- @param heading status - The text to appear in the heading, if different than the status
-- @return string
function List:renderStatusList(status, heading)
-- Get all cards for the given status
local cards = self:getCardsByStatus(status)
-- If there are no cards, return empty string and end early
if (#cards == 0) then return '' end
local heading = mw.html.create('h2'):wikitext(heading or status)
local list = mw.html.create('table'):addClass('wikitable sortable')
local headingRow = list:tag('tr')
headingRow:tag('th'):wikitext('Card')
headingRow:tag('th'):wikitext('Card type')
headingRow:tag('th'):wikitext('Status')
headingRow:tag('th'):wikitext('Changes')
for _, card in pairs(cards) do
local cardTypeLink = card.cardType
and ('[[' .. card.cardType .. '|' .. string.gsub(card.cardType, ' Card', '') .. ']]')
or ''
-- Form the CSS class that styles the cells in the status column
local statusClass = 'status-' .. (card.status):lower()
local row = list:tag('tr')
row:tag('td'):wikitext('[[' .. card.link .. '|' .. (card.name or card.link) .. ']]')
row:tag('td'):wikitext(cardTypeLink)
row:tag('td'):addClass(statusClass):wikitext('[[' .. card.status .. ']]')
row:tag('td'):wikitext(card.prevStatus and 'was [[' .. card.prevStatus .. ']]' or '')
end
return tostring(heading) .. tostring(list)
end
-- Check if something has been filled out
-- i.e. check that it's neither `nil` nor empty string
-- @param value mixed
-- @return bool
function isFilled(value)
return value ~= nil and value ~= ''
end
return List