Module:Card
Appearance
| Main | Documentation | Usage |
This Lua module is used primarily on pages in the Main namespace. It can be found on 2,433 pages, or on about 60.66% of those pages.
Edits to this Lua module will be widely noticed. To avoid large-scale disruption and unnecessary server load, any changes to this Lua module should be tested in its sandbox or testcases subpages. The tested changes can then be added to this page in one single edit.
Please consider discussing any changes in the wiki's Discord.
This module implements {{Card}}.
To update, see: Module:CentralData.
local p = {}
local lib = require('Module:Feature')
local ne = lib.isNotEmpty
local TemplateData = require('Module:TemplateData')
local array = require('Module:Array')
local allData = {
-- {'Neighbor', mw.loadData('Module:CentralData/Neighbors')},
{'Creature', mw.loadData('Module:CentralData/Creatures')},
-- {'Furniture', mw.loadData('Module:CentralData/Furniture')},
{'Item', mw.loadData('Module:CentralData/Items')},
}
-- Minimal TemplateData args.
-- This does not need to be huge unless you want full documentation for every parameter.
local CARD_ARGS = {
{
name = 'name',
alias = 1,
default = 'Unknown',
},
{
name = 'label',
alias = {2, 'text', 'count', 'amount', 'x'},
},
{
name = 'show_label',
alias = 'show_text',
type = '1',
},
{
name = 'quality',
alias = 'rarity',
default = 'Gray',
},
{
name = 'type',
default = 'Item',
},
{
name = 'suffix',
default = '',
},
{
name = 'image',
},
{
name = 'image_size',
alias = 'imageSize',
},
{
name = 'image_ext',
alias = {'imageExt', 'extension'},
default = 'png',
},
{
name = 'link',
},
{
name = 'link_suffix',
default = '',
},
{
name = 'nolink',
type = '1',
},
{
name = 'caption',
},
{
name = 'show_caption',
type = '1',
},
{
name = 'caption_width',
alias = 'captionWidth',
},
{
name = 'mini',
type = '1',
},
{
name = 'first',
type = '1',
},
{
name = 'up',
alias = 'UP',
type = '1',
},
{
name = 'galaxy',
},
{
name = 'notice',
},
}
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrapper = { 'Template:Card' },
parentOnly = false
})
return p._main(args)
end
function p.getTypeAndData(name, requestedType)
local img_type = requestedType or 'Item'
local img_data = nil
for _, v in ipairs(allData) do
local dataType = v[1]
local dataTable = v[2]
if lib.isEmpty(requestedType) or dataType == requestedType then
local data = dataTable[name]
if data then
img_type = dataType
img_data = data
break
end
end
end
return img_type, img_data
end
local function normalizeBool(value)
return value == true or value == '1' or value == 1 or value == 'yes'
end
local function normalizeClassName(value)
return tostring(value or '')
:lower()
:gsub('%s+', '-')
end
local function normalizeQuality(quality)
quality = tostring(quality or '')
if quality:find(';', 1, true) then
quality = array._main({
quality,
';',
firstItemOnly = 1
})
end
if lib.isEmpty(quality) then
quality = 'Gray'
end
return normalizeClassName(quality)
end
local function setCaptionWidth(node, width)
if width == 'auto' or lib.isEmpty(width) then
node:addClass('auto-width')
else
node:css('width', width)
end
end
function p._processArgs(args)
local out = TemplateData.processArgs(args, CARD_ARGS)
-- Basic identity
out.name = out.name or 'Unknown'
-- Data lookup
out.type, out.data = p.getTypeAndData(out.name, out.type)
-- Boolean-ish params
out.mini = normalizeBool(out.mini)
out.first = normalizeBool(out.first)
out.up = normalizeBool(out.up)
out.nolink = normalizeBool(out.nolink)
out.show_label = normalizeBool(out.show_label)
out.show_caption = normalizeBool(out.show_caption)
-- Image defaults
out.suffix = out.suffix or ''
out.image_ext = out.image_ext or 'png'
if lib.isEmpty(out.image_size) then
out.image_size = out.mini and 48 or 70
end
if lib.isEmpty(out.suffix) then
out.suffix = ' Icon'
end
-- Data-driven name
out.data_name = out.data and out.data.name or nil
-- Quality / rarity
if lib.isEmpty(out.quality) and out.data and out.data.quality then
out.quality = out.data.quality
end
out.quality = normalizeQuality(out.quality)
-- Galaxy
if lib.isEmpty(out.galaxy) and out.data and out.data.galaxy then
out.galaxy = out.data.galaxy
end
-- Label/text handling
if out.show_label then
out.label = out.data_name or out.name
end
if out.label == '0' then
out.label = nil
end
-- Type-specific behavior
local lcType = tostring(out.type or ''):lower()
if lcType == 'neighbor' then
if lib.isEmpty(out.label) then
if out.mini and out.data and out.data.shortName then
out.label = out.data.shortName
elseif not out.mini then
out.label = out.name
end
end
-- Account for transparent borders on neighbor icons
if tonumber(out.image_size) then
out.image_size = tonumber(out.image_size) + 2
end
end
-- Caption handling
if out.show_caption and lib.isEmpty(out.caption) then
out.caption = out.data_name or out.name
end
-- Link handling
if out.link == nil then
out.link = lib.ternary(out.name == 'Unknown', '', out.name)
end
out.link_suffix = out.link_suffix or ''
out.final_link = out.link .. out.link_suffix
if out.nolink then
out.final_link = ''
end
-- File name
if ne(out.image) then
out.final_file = out.image
else
out.final_file = lib.sanitizeFileName(out.name) .. out.suffix .. '.' .. out.image_ext
end
-- Main image wikitext
local linkPart = out.nolink and '|link=' or ('|link=' .. out.final_link)
out.image_wikitext = table.concat({
'[[File:',
out.final_file,
'|',
out.image_size,
'px|alt=',
out.name,
linkPart,
']]'
})
return out
end
function p._main(args)
local a = p._processArgs(args)
local node_container = mw.html.create('div')
:addClass('card-container')
if a.mini then
node_container:addClass('mini-card')
end
-- Old-style wrapper/body structure.
-- This is usually important if your existing CSS was written for the old Card module.
local node_card = node_container:tag('span')
:addClass('card-wrapper')
:tag('span')
:addClass('card-body')
-- Main image container
node_card:tag('span')
:addClass('card-image-container')
:addClass('card-quality-' .. a.quality)
:wikitext(a.image_wikitext)
-- Galaxy icon
if not a.mini and ne(a.galaxy) then
node_card:addClass('card-galaxy-' .. normalizeClassName(a.galaxy))
node_card:tag('span')
:addClass('card-icon-galaxy')
:wikitext(
'[[File:Icon ' ..
a.galaxy ..
'.png|alt=' ..
a.galaxy ..
'|link=' ..
a.galaxy ..
'|20px]]'
)
end
-- Notice label
if not a.mini and ne(a.notice) then
node_card:tag('span')
:addClass('card-notice-label')
:wikitext(a.notice)
end
-- First modifier
if a.first then
node_card:tag('span')
:addClass('card-modifier')
:addClass('card-modifier-first')
:wikitext('[[File:Icon Item First.png|x25px|link=|alt=First]]')
end
-- UP modifier
if a.up then
node_card:tag('span')
:addClass('card-modifier')
:addClass('card-modifier-up')
:wikitext('[[File:Icon Item UP.png|x25px|link=|alt=UP]]')
end
-- Label/text below card image
if ne(a.label) then
node_container:tag('span')
:addClass('card-label')
:wikitext(a.label)
end
-- Caption below card
if a.show_caption and ne(a.caption) then
local node_caption = node_container:tag('span')
:addClass('card-caption')
if a.nolink or lib.isEmpty(a.final_link) then
node_caption:wikitext(a.caption)
else
node_caption:wikitext('[[', a.final_link, '|', a.caption, ']]')
end
setCaptionWidth(node_caption, a.caption_width)
end
return tostring(node_container)
end
function p.templateData(frame)
return TemplateData.templateData(CARD_ARGS, {
description = 'Creates an item-style card with image, quality, label, caption, modifiers, and optional data-driven icons.',
format = 'inline'
}, frame)
end
function p.syntax(frame)
return TemplateData.syntax(CARD_ARGS, frame)
end
return p