Module:Icon: Difference between revisionsGive feedback
Gammaton32 (talk | contribs) updated aliases |
Switch to pre-built lookup table for faster page rendering |
||
| Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local iconData = mw.loadJsonData("Data:ResourceLookup.json") | |||
local lang_codes = mw.loadJsonData("Data:LangCodes.json") | local lang_codes = mw.loadJsonData("Data:LangCodes.json") | ||
local cachedLangCode, cachedLangData | local cachedLangCode, cachedLangData | ||
local linkOverrides = { | |||
["Bullet Lifesteal"] = "Bullet Lifesteal (item)", | |||
["Spirit Lifesteal"] = "Spirit Lifesteal (item)" | |||
} | |||
local missingImageOverrides = { | local missingImageOverrides = { | ||
["boho"] = "Module-Icon missing.png", | ["boho"] = "Module-Icon missing.png", | ||
["druid"] = "Module-Icon missing.png", | ["druid"] = "Module-Icon missing.png", | ||
["fortuna"] = "Module-Icon missing.png", | ["fortuna"] = "Module-Icon missing.png", | ||
["graf"] = "Module-Icon missing.png", | ["graf"] = "Module-Icon missing.png", | ||
| Line 22: | Line 20: | ||
["swan"] = "Module-Icon missing.png", | ["swan"] = "Module-Icon missing.png", | ||
["thumper"] = "Module-Icon missing.png", | ["thumper"] = "Module-Icon missing.png", | ||
} | } | ||
local aliases = { | |||
local | ["doorman"] = "the doorman", | ||
[" | ["mo and krill"] = "mo & krill", | ||
[" | ["mo"] = "mo & krill", | ||
["krill"] = "mo & krill", | |||
["curse"] = "cursed relic", | |||
["debuff remover"] = "dispel magic", | |||
["defend and fight!"] = "plot armor", | |||
["conjure dragon"] = "bookwyrm", | |||
["backstabber"] = "stalker", | |||
["flying strike"] = "flying slash", | |||
["tornado"] = "dust devil", | |||
["kudzu bomb"] = "entangling thorns", | |||
} | } | ||
local function getLangData() | local function getLangData() | ||
if cachedLangData then | if cachedLangData then | ||
| Line 196: | Line 58: | ||
cachedLangCode = langCode | cachedLangCode = langCode | ||
cachedLangData = langData | cachedLangData = langData | ||
return langCode, langData | |||
end | |||
-- Infer image path from name, with override support for missing images | |||
local function getImage(iconInfo) | |||
local lowerName = iconInfo.name:lower() | |||
return missingImageOverrides[lowerName] or (iconInfo.name .. ".png") | |||
end | |||
return | -- Infer link from type and available fields | ||
local function getLink(iconInfo) | |||
if iconInfo.type == "ability" then | |||
return iconInfo.hero_name or iconInfo.name | |||
end | |||
return linkOverrides[iconInfo.name] or iconInfo.name | |||
end | end | ||
function p.render(frame) | function p.render(frame) | ||
local args = frame:getParent().args | local args = frame:getParent().args | ||
local name = args[1] or "" | local name = args[1] or "" | ||
local lowerName = name:lower() | |||
if aliases[lowerName] then | |||
lowerName = aliases[lowerName] | |||
end | |||
local iconInfo = iconData[lowerName] | |||
if not iconInfo then | |||
return string.format("[[:Category:Module:Icon ERROR|Icon not found]] ('%s'). [[Category:Module:Icon ERROR]]", name) | |||
end | |||
local customText = args.l1 or "" | local customText = args.l1 or "" | ||
local size = args.size or "20px" | local size = args.size or "20px" | ||
local noLink = args["no-link"] == "true" | local noLink = args["no-link"] == "true" | ||
local iconOnly = args["icon-only"] == "true" | local iconOnly = args["icon-only"] == "true" | ||
for k, v in pairs(args) do | for k, v in pairs(args) do | ||
if type(k) == "number" and k > 1 then | if type(k) == "number" and k > 1 then | ||
local val = mw.text.trim(v) | local val = mw.text.trim(v) | ||
if val == "icon-only" then iconOnly = true | |||
if val == "icon-only" then | elseif val == "no-link" then noLink = true | ||
elseif val:match("^%d+px$") then size = val end | |||
elseif val == "no-link" then | |||
elseif val:match("^%d+px$") then | |||
end | end | ||
end | end | ||
local langCode, langData = getLangData() | |||
local | |||
local | local displayName = customText | ||
if displayName == "" then | |||
if iconInfo.key and langData[iconInfo.key] then | |||
displayName = langData[iconInfo.key] | |||
else | |||
displayName = iconInfo.name | |||
end | |||
end | end | ||
local baseLink = getLink(iconInfo) | |||
local baseLink = | |||
local link = baseLink | local link = baseLink | ||
if langCode ~= "en" and baseLink ~= "" then | if langCode ~= "en" and baseLink ~= "" then | ||
link = baseLink .. "/" .. langCode | link = baseLink .. "/" .. langCode | ||
end | end | ||
-- | -- Abilities get the module-icon-ability class for light/dark theme filter support | ||
local style | local style | ||
if | if iconInfo.type == "ability" then | ||
style = 'class="module-icon-ability" style="position:relative; bottom:2px;"' | style = 'class="module-icon-ability" style="position:relative; bottom:2px;"' | ||
else | else | ||
| Line 261: | Line 129: | ||
end | end | ||
local image = getImage(iconInfo) | |||
local imageLink = noLink and "" or link | local imageLink = noLink and "" or link | ||
local iconHtml = string.format('<span %s>[[File:%s|%s|link=%s]]</span>', style, | local iconHtml = string.format('<span %s>[[File:%s|%s|link=%s]]</span>', style, image, size, imageLink) | ||
if iconOnly or displayName == "" then | if iconOnly or displayName == "" then | ||
Revision as of 14:16, 11 March 2026
Main module for rendering game icons.
Note: This module is not intended for direct use. Use the templates below.
Data sources
The module reads from Data:ResourceLookup.json, a pre-indexed lookup table generated by Deadbot at deploy time. When the bot uploads new game files, hero, ability, and item icons update automatically.
An additional resource for other icons can be found at Data:ResourceLookup2.json, a manually maintained table; some entries may rely on a dictionary key.
See Module:Icon/data for manual overrides, legacy items, aliases, and renames used by this module.
Usage
Any of the following templates can be used. The module automatically detects the icon type:
{{HeroIcon}}{{AbilityIcon}}{{ItemIcon}}{{EntityIcon}}
Note: While all four templates work identically, it is recommended to use the appropriate one for clarity (e.g., use {{AbilityIcon|Siphon Life}} even though {{HeroIcon|Siphon Life}} will also work).
Error tracking
Icons that fail to render are added to Category:Module:Icon ERROR.
local p = {}
local iconData = mw.loadJsonData("Data:ResourceLookup.json")
local lang_codes = mw.loadJsonData("Data:LangCodes.json")
local cachedLangCode, cachedLangData
local linkOverrides = {
["Bullet Lifesteal"] = "Bullet Lifesteal (item)",
["Spirit Lifesteal"] = "Spirit Lifesteal (item)"
}
local missingImageOverrides = {
["boho"] = "Module-Icon missing.png",
["druid"] = "Module-Icon missing.png",
["fortuna"] = "Module-Icon missing.png",
["graf"] = "Module-Icon missing.png",
["gunslinger"] = "Module-Icon missing.png",
["skyrunner"] = "Module-Icon missing.png",
["swan"] = "Module-Icon missing.png",
["thumper"] = "Module-Icon missing.png",
}
local aliases = {
["doorman"] = "the doorman",
["mo and krill"] = "mo & krill",
["mo"] = "mo & krill",
["krill"] = "mo & krill",
["curse"] = "cursed relic",
["debuff remover"] = "dispel magic",
["defend and fight!"] = "plot armor",
["conjure dragon"] = "bookwyrm",
["backstabber"] = "stalker",
["flying strike"] = "flying slash",
["tornado"] = "dust devil",
["kudzu bomb"] = "entangling thorns",
}
local function getLangData()
if cachedLangData then
return cachedLangCode, cachedLangData
end
local title = mw.title.getCurrentTitle().fullText
local subpageLang = title:match("/([^/]+)$")
local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en"
local langData = {}
if langCode ~= "en" then
local success, data = pcall(function()
return mw.loadJsonData("Data:Lang " .. langCode .. ".json")
end)
if success and type(data) == "table" then
langData = data
end
end
cachedLangCode = langCode
cachedLangData = langData
return langCode, langData
end
-- Infer image path from name, with override support for missing images
local function getImage(iconInfo)
local lowerName = iconInfo.name:lower()
return missingImageOverrides[lowerName] or (iconInfo.name .. ".png")
end
-- Infer link from type and available fields
local function getLink(iconInfo)
if iconInfo.type == "ability" then
return iconInfo.hero_name or iconInfo.name
end
return linkOverrides[iconInfo.name] or iconInfo.name
end
function p.render(frame)
local args = frame:getParent().args
local name = args[1] or ""
local lowerName = name:lower()
if aliases[lowerName] then
lowerName = aliases[lowerName]
end
local iconInfo = iconData[lowerName]
if not iconInfo then
return string.format("[[:Category:Module:Icon ERROR|Icon not found]] ('%s'). [[Category:Module:Icon ERROR]]", name)
end
local customText = args.l1 or ""
local size = args.size or "20px"
local noLink = args["no-link"] == "true"
local iconOnly = args["icon-only"] == "true"
for k, v in pairs(args) do
if type(k) == "number" and k > 1 then
local val = mw.text.trim(v)
if val == "icon-only" then iconOnly = true
elseif val == "no-link" then noLink = true
elseif val:match("^%d+px$") then size = val end
end
end
local langCode, langData = getLangData()
local displayName = customText
if displayName == "" then
if iconInfo.key and langData[iconInfo.key] then
displayName = langData[iconInfo.key]
else
displayName = iconInfo.name
end
end
local baseLink = getLink(iconInfo)
local link = baseLink
if langCode ~= "en" and baseLink ~= "" then
link = baseLink .. "/" .. langCode
end
-- Abilities get the module-icon-ability class for light/dark theme filter support
local style
if iconInfo.type == "ability" then
style = 'class="module-icon-ability" style="position:relative; bottom:2px;"'
else
style = 'style="position:relative; bottom:2px;"'
end
local image = getImage(iconInfo)
local imageLink = noLink and "" or link
local iconHtml = string.format('<span %s>[[File:%s|%s|link=%s]]</span>', style, image, size, imageLink)
if iconOnly or displayName == "" then
return iconHtml
end
local textHtml = (noLink or link == "") and displayName or string.format('[[%s|%s]]', link, displayName)
return '<span style="white-space:nowrap;">' .. iconHtml .. " " .. textHtml .. '</span>'
end
return p