Module:ItemUtils
Jump to navigation
Jump to search
Documentation for this module may be created at Module:ItemUtils/doc
-- Module:ItemUtils
-- =============================================================================
-- Shared helper functions used by Module:Item's renderers.
-- Notable: contains ZERO renderers. Those live in Module:Item.
-- This distinction matters. Please remember it.
-- =============================================================================
local p = {}
-- =============================================================================
-- p.buildInfobox
-- =============================================================================
-- Builds an infobox by calling {{Infobox}} via frame:expandTemplate().
--
-- config table accepts:
-- config.title (string) — item name in the header
-- config.image (string) — filename only, we handle the [[File:]] wrap
-- config.subheader (string) — short description below the image
-- config.item_id (string) — goes in the collapsible footer
-- config.added (string) — version added
-- config.rows (table) — array of row definitions:
-- {"Label", value} → standard data row
-- {header = "Title"} → full-width section header
-- {full = content} → full-width data row (stat bars etc.)
-- Rows with nil/empty values are silently skipped.
-- =============================================================================
function p.buildInfobox(config)
local frame = mw.getCurrentFrame()
local args = {}
args.title = config.title
args.labelstyle = "width:50%;"
if config.image and config.image ~= "" then
args.image = "[[File:" .. config.image .. "|frameless]]"
end
if config.subheader and config.subheader ~= "" then
args.subheader = config.subheader
end
if config.item_id and config.item_id ~= "" then
args.below =
'<div class="mw-collapsible mw-collapsed" ' ..
'data-expandtext="show item id" ' ..
'data-collapsetext="hide item id">' ..
'<br><div class="mw-collapsible-content" style="display:none;">' ..
config.item_id ..
'</div></div>' ..
'<div class="no-js-fallback">' .. config.item_id .. '</div>'
end
local n = 1
if config.added and config.added ~= "" then
args["label" .. n] = "Added"
args["data" .. n] = config.added
n = n + 1
end
for _, row in ipairs(config.rows) do
if row.header then
-- Named key: {header = "Section Title"}
-- Using named keys because single-element tables and nil values
-- have a complicated relationship in Lua that we want no part of.
args["header" .. n] = row.header
n = n + 1
elseif row.full ~= nil and tostring(row.full) ~= "" then
-- Full-width data row: {full = content}
-- Used for StatRow bars which span the full infobox width.
args["data" .. n] = tostring(row.full)
n = n + 1
elseif row[1] ~= nil and row[2] ~= nil and tostring(row[2]) ~= "" then
-- Standard label/data row: {"Label", value}
-- Explicitly checks row[2] ~= nil rather than trusting #row,
-- because #row lies to your face when row[2] is nil.
args["label" .. n] = row[1]
args["data" .. n] = tostring(row[2])
n = n + 1
end
-- nil values, empty strings, and broken dreams fall through silently.
end
return frame:expandTemplate{ title = "Infobox", args = args }
end
-- =============================================================================
-- The remaining helpers — all unchanged, all minding their own business
-- in their own module like they're supposed to.
-- =============================================================================
function p.tierStars(tier)
tier = tonumber(tier)
if not tier then return "Unknown" end
return string.rep("★", tier) .. string.rep("☆", 6 - tier)
end
function p.link(target)
if not target or target == "" then return "—" end
return "[[" .. target .. "]]"
end
function p.linkList(items)
if not items or #items == 0 then return "—" end
local links = {}
for _, item in ipairs(items) do
table.insert(links, "[[" .. item .. "]]")
end
return table.concat(links, ", ")
end
function p.error(msg)
return '<span style="color:#ff4444; font-weight:bold; ' ..
'background:#2a0000; padding:2px 6px;">' ..
'⚠ ItemUtils Error: ' .. tostring(msg) ..
'</span>'
end
return p