Module:MobVariants
Appearance
Documentation for this module may be created at Module:MobVariants/doc
local p = {}
local variantKeys = { "a", "b", "c" }
local function trim(s)
if not s then
return ""
end
return mw.text.trim(s)
end
local function hasValue(s)
return trim(s) ~= ""
end
local function splitAndSort(raw, delimiter)
delimiter = delimiter or ","
local results = {}
if not hasValue(raw) then
return results
end
local items = mw.text.split(raw, delimiter)
for _, item in ipairs(items) do
local value = trim(item)
if value ~= "" then
table.insert(results, value)
end
end
table.sort(results, function(a, b)
return mw.ustring.lower(a) < mw.ustring.lower(b)
end)
return results
end
local function makeBulletedList(items)
if not items or #items == 0 then
return ""
end
local itemCount = #items
local columnCount = 1
if itemCount >= 16 then
columnCount = 3
elseif itemCount >= 8 then
columnCount = 2
end
local output = {
string.format('<div style="column-count: %d; column-gap: 0.5em;">', columnCount),
'<ul style="margin: 0; padding-left: 0.5em;">'
}
for _, item in ipairs(items) do
table.insert(output, string.format('<li style="break-inside: avoid;">[[%s]]</li>', item))
end
table.insert(output, '</ul>')
table.insert(output, '</div>')
return table.concat(output)
end
local function makeBulletedListCompact(items)
if not items or #items == 0 then
return ""
end
local itemCount = #items
local columnCount = 1
if itemCount >= 8 then
columnCount = 2
end
local output = {
string.format('<div style="column-count: %d; column-gap: 2em;">', columnCount),
'<ul style="margin: 0; padding-left: 1.2em;">'
}
for _, item in ipairs(items) do
table.insert(output, string.format('<li style="break-inside: avoid;">[[%s]]</li>', item))
end
table.insert(output, '</ul>')
table.insert(output, '</div>')
return table.concat(output)
end
local function makeInlineList(items)
if not items or #items == 0 then
return ""
end
local linked = {}
for _, item in ipairs(items) do
table.insert(linked, string.format('[[%s]]', item))
end
return table.concat(linked, ", ")
end
local function formatLevelRange(low, high)
low = trim(low)
high = trim(high)
if low ~= "" and high ~= "" then
if low == high then
return low
end
return low .. " - " .. high
elseif low ~= "" then
return low
elseif high ~= "" then
return high
end
return ""
end
local function collectVariants(frame)
local args = frame.args
local variants = {}
for _, key in ipairs(variantKeys) do
local region = trim(args["region_" .. key] or "")
local levelLow = trim(args["level_low_" .. key] or "")
local levelHigh = trim(args["level_high_" .. key] or "")
local lootRaw = trim(args["loot_table_" .. key] or "")
local harvestRaw = trim(args["harvest_table_" .. key] or "")
local hasData =
region ~= "" or
levelLow ~= "" or
levelHigh ~= "" or
lootRaw ~= "" or
harvestRaw ~= ""
if hasData then
table.insert(variants, {
key = key,
region = region,
levelLow = levelLow,
levelHigh = levelHigh,
levelDisplay = formatLevelRange(levelLow, levelHigh),
lootItems = splitAndSort(lootRaw, ","),
harvestItems = splitAndSort(harvestRaw, ",")
})
end
end
return variants
end
local function renderSingleVariant(variant)
local output = {}
local details = {}
if variant.region ~= "" then
table.insert(details, "'''Region:''' " .. variant.region)
end
if variant.levelDisplay ~= "" then
table.insert(details, "'''Level:''' " .. variant.levelDisplay)
end
if #details > 0 then
table.insert(output, '<div style="margin-left: 1em;">')
table.insert(output, table.concat(details, "<br />\n"))
table.insert(output, '</div>')
end
if variant.harvestItems and #variant.harvestItems > 0 then
table.insert(output, '==Harvest==')
table.insert(output, '<div style="margin-left: 1em;">')
table.insert(output, makeBulletedList(variant.harvestItems))
table.insert(output, '</div>')
end
if variant.lootItems and #variant.lootItems > 0 then
table.insert(output, '==Drops==')
table.insert(output, '<div style="margin-left: 1em;">')
table.insert(output, makeBulletedList(variant.lootItems))
table.insert(output, '</div>')
end
return table.concat(output, "\n")
end
local function renderMultipleVariants(variants)
local output = {}
table.insert(output, '==Variants==')
table.insert(output, '{| class="wikitable" style="width: 100%;"')
table.insert(output, '! Region')
table.insert(output, '! Level')
table.insert(output, '! Harvest')
table.insert(output, '! Drops')
for _, variant in ipairs(variants) do
local region = variant.region ~= "" and variant.region or "—"
local level = variant.levelDisplay ~= "" and variant.levelDisplay or "—"
local harvest = (#variant.harvestItems > 0) and makeBulletedListCompact(variant.harvestItems) or "—"
local loot = (#variant.lootItems > 0) and makeBulletedListCompact(variant.lootItems) or "—"
table.insert(output, '|-')
table.insert(output, '| ' .. region)
table.insert(output, '| ' .. level)
table.insert(output, '| ' .. harvest)
table.insert(output, '| ' .. loot)
end
table.insert(output, '|}')
return table.concat(output, "\n")
end
function p.render(frame)
local variants = collectVariants(frame)
if #variants == 0 then
return ""
elseif #variants == 1 then
return renderSingleVariant(variants[1])
else
return renderMultipleVariants(variants)
end
end
return p