Module:Icon: Difference between revisionsGive feedback
m also applies to a few removed items. |
mNo edit summary |
||
| (43 intermediate revisions by 7 users not shown) | |||
| Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local iconDataRaw = mw.loadJsonData("Data:ResourceLookup.json") | |||
local | local iconData2 = mw.loadJsonData("Data:ResourceLookup2.json") | ||
local dictionary = mw.loadJsonData("Data:Dictionary") | |||
local iconData = {} | |||
for k, v in pairs(iconDataRaw) do | |||
iconData[k] = v | |||
end | |||
for k, v in pairs(iconData2) do | |||
iconData[k] = v | |||
end | |||
local lang_codes = mw.loadJsonData("Data:LangCodes.json") | local lang_codes = mw.loadJsonData("Data:LangCodes.json") | ||
local lang_module = require("Module:Lang") | |||
local table_data = require("Module:Icon/data") | |||
local cachedLangCode | |||
local cachedLangCode | |||
local linkOverrides = table_data.linkOverrides | |||
local | local legacyItems = table_data.legacyItems | ||
local missingImageOverrides = table_data.missingImageOverrides | |||
local aliases = table_data.aliases | |||
local renames = table_data.renames | |||
local function getLangCode() | |||
local function | if cachedLangCode then | ||
if | return cachedLangCode | ||
return cachedLangCode | |||
end | end | ||
| Line 27: | Line 36: | ||
local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en" | local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en" | ||
cachedLangCode = langCode | |||
return langCode | |||
end | |||
-- Infer image path from name, with override support for missing images | |||
if | local function getImage(iconInfo, args) | ||
local lowerName = iconInfo.name:lower() | |||
if args.image then | |||
return args.image | |||
end | |||
return missingImageOverrides[lowerName] or (iconInfo.name .. ".png") | |||
end | |||
-- Get the translated name | |||
local function getTranslatedName(iconInfo, langCode) | |||
if langCode == "en" then | |||
return iconInfo.name | |||
end | |||
-- 1. Direct key | |||
if iconInfo.key and iconInfo.key ~= "" then | |||
local translated = lang_module.get_string(iconInfo.key, langCode, iconInfo.name | |||
) | |||
if type(translated) == "string" then | |||
return (translated:gsub("<[^>]+>", "")) | |||
end | end | ||
return iconInfo.name | |||
end | end | ||
-- 2. Dictionary lookup | |||
if iconInfo.key_dictionary and iconInfo.key_dictionary ~= "" then | |||
local entry = dictionary[iconInfo.key_dictionary] | |||
if type(entry) == "table" then | |||
return entry[langCode] | |||
or entry.en | |||
or iconInfo.name | |||
end | |||
end | |||
-- No valid key > fallback | |||
return iconInfo.name | |||
end | |||
-- Infer link from type and available fields | |||
local function getLink(iconInfo, langCode) | |||
if iconInfo.type == "ability" then | |||
local hero = iconInfo.hero_name or iconInfo.name | |||
-- Get the translated name for the specific ability | |||
local abilityName = getTranslatedName(iconInfo, langCode) | |||
-- Format for URL: replace spaces with underscores | |||
local anchor = abilityName:gsub(" ", "_") | |||
return hero .. "#" .. anchor | |||
end | |||
return linkOverrides[iconInfo.name] or iconInfo.name | |||
end | |||
-- Returns the canonical display name for a given user input | |||
-- Used by templates to store the correct casing in data attributes | |||
-- Normalizes casing so exact string matches work reliably in Lua modules | |||
function p.getCanonicalName(frame) | |||
local name = frame.args[1] or "" | |||
local lowerName = name:lower() | |||
if renames[lowerName] then | |||
lowerName = renames[lowerName] | |||
elseif aliases[lowerName] then | |||
lowerName = aliases[lowerName] | |||
end | |||
local iconInfo = iconData[lowerName] or legacyItems[lowerName] | |||
-- If unknown, return original input | |||
if not iconInfo then | |||
return name | |||
end | |||
-- Quick hack: ability names are used by MediaWiki:Gadget-infobox-tooltip.js and expected to be localized | |||
local langCode = getLangCode() | |||
if iconInfo.type == "ability" then | |||
return getTranslatedName(iconInfo, langCode) | |||
end | |||
return | return iconInfo.name | ||
end | end | ||
local function render(name, args) | |||
local originalName = name | |||
local | local lowerName = name:lower() | ||
local | args = args or {} | ||
local customText = args.l1 or "" | |||
if renames[lowerName] then | |||
lowerName = renames[lowerName] | |||
elseif aliases[lowerName] then | |||
lowerName = aliases[lowerName] | |||
end | |||
-- Lookup live data > legacy fallback | |||
local iconInfo = iconData[lowerName] or legacyItems[lowerName] | |||
-- Throw error if not found | |||
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 ~= "" and args.l1 or nil | |||
local customLink = args.link ~= "" and args.link or nil | |||
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 noFile = args["no-file"] == "true" | |||
local iconOnly = args["icon-only"] == "true" | local iconOnly = args["icon-only"] == "true" | ||
local | for k, v in pairs(args) do | ||
if | 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 = getLangCode() | |||
local displayName | |||
if customText then | |||
displayName = customText | |||
elseif renames[name:lower()] then | |||
-- Preserve original if renamed | |||
displayName = originalName | |||
else | |||
displayName = getTranslatedName(iconInfo, langCode) | |||
end | end | ||
local | local baseLink = customLink or getLink(iconInfo, langCode) | ||
local | local fragment = "" | ||
-- | -- Split the fragment (#Abilities) from the base link | ||
if baseLink:find("#") then | |||
local parts = mw.text.split(baseLink, "#", true) | |||
baseLink = parts[1] | |||
fragment = "#" .. (parts[2] or "") | |||
end | |||
local link = baseLink | |||
local link = | |||
if not customLink and langCode ~= "en" and baseLink ~= "" then | |||
link = baseLink .. "/" .. langCode | |||
end | end | ||
-- Reattach fragment at the end | |||
link = link .. fragment | |||
-- Add CSS class for abilities | |||
local style | |||
if iconInfo.type == "ability" then | |||
style = 'class="module-icon-ability" style="position:relative; bottom:2px;"' | |||
else | |||
style = 'class="c-icon" style="position:relative; bottom:2px;"' | |||
end | |||
local imageLink = noLink and "" or link | |||
local iconHtml = "" | |||
if not noFile then | |||
local image = getImage(iconInfo, args) | |||
iconHtml = string.format('<span %s>[[File:%s|%s|link=%s]]</span>', style, image, size, imageLink) | |||
end | |||
if iconOnly or displayName == "" then | |||
return iconHtml | |||
end | |||
local textHtml = (noLink or link == "") and displayName or string.format('[[%s|%s]]', link, displayName) | |||
if iconHtml ~= "" then | |||
return '<span style="white-space:nowrap;">' .. iconHtml .. " " .. textHtml .. '</span>' | |||
else | |||
return textHtml | |||
end | |||
end | |||
-- Template entrypoint | |||
function p.render(frame) | |||
local args = frame:getParent().args | |||
local name = args[1] or "" | |||
return render(name, args) | |||
end | |||
-- Module entrypoint | |||
return | function p._render(name, args) | ||
return render(name, args) | |||
end | end | ||
return p | return p | ||
Latest revision as of 14:07, 29 July 2026
Main module for rendering game icons.
Note: This module is not intended for direct use. Use the templates below.
Data sources
[edit source]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
[edit source]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
[edit source]Icons that fail to render are added to Category:Module:Icon ERROR.
local p = {}
local iconDataRaw = mw.loadJsonData("Data:ResourceLookup.json")
local iconData2 = mw.loadJsonData("Data:ResourceLookup2.json")
local dictionary = mw.loadJsonData("Data:Dictionary")
local iconData = {}
for k, v in pairs(iconDataRaw) do
iconData[k] = v
end
for k, v in pairs(iconData2) do
iconData[k] = v
end
local lang_codes = mw.loadJsonData("Data:LangCodes.json")
local lang_module = require("Module:Lang")
local table_data = require("Module:Icon/data")
local cachedLangCode
local linkOverrides = table_data.linkOverrides
local legacyItems = table_data.legacyItems
local missingImageOverrides = table_data.missingImageOverrides
local aliases = table_data.aliases
local renames = table_data.renames
local function getLangCode()
if cachedLangCode then
return cachedLangCode
end
local title = mw.title.getCurrentTitle().fullText
local subpageLang = title:match("/([^/]+)$")
local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en"
cachedLangCode = langCode
return langCode
end
-- Infer image path from name, with override support for missing images
local function getImage(iconInfo, args)
local lowerName = iconInfo.name:lower()
if args.image then
return args.image
end
return missingImageOverrides[lowerName] or (iconInfo.name .. ".png")
end
-- Get the translated name
local function getTranslatedName(iconInfo, langCode)
if langCode == "en" then
return iconInfo.name
end
-- 1. Direct key
if iconInfo.key and iconInfo.key ~= "" then
local translated = lang_module.get_string(iconInfo.key, langCode, iconInfo.name
)
if type(translated) == "string" then
return (translated:gsub("<[^>]+>", ""))
end
return iconInfo.name
end
-- 2. Dictionary lookup
if iconInfo.key_dictionary and iconInfo.key_dictionary ~= "" then
local entry = dictionary[iconInfo.key_dictionary]
if type(entry) == "table" then
return entry[langCode]
or entry.en
or iconInfo.name
end
end
-- No valid key > fallback
return iconInfo.name
end
-- Infer link from type and available fields
local function getLink(iconInfo, langCode)
if iconInfo.type == "ability" then
local hero = iconInfo.hero_name or iconInfo.name
-- Get the translated name for the specific ability
local abilityName = getTranslatedName(iconInfo, langCode)
-- Format for URL: replace spaces with underscores
local anchor = abilityName:gsub(" ", "_")
return hero .. "#" .. anchor
end
return linkOverrides[iconInfo.name] or iconInfo.name
end
-- Returns the canonical display name for a given user input
-- Used by templates to store the correct casing in data attributes
-- Normalizes casing so exact string matches work reliably in Lua modules
function p.getCanonicalName(frame)
local name = frame.args[1] or ""
local lowerName = name:lower()
if renames[lowerName] then
lowerName = renames[lowerName]
elseif aliases[lowerName] then
lowerName = aliases[lowerName]
end
local iconInfo = iconData[lowerName] or legacyItems[lowerName]
-- If unknown, return original input
if not iconInfo then
return name
end
-- Quick hack: ability names are used by MediaWiki:Gadget-infobox-tooltip.js and expected to be localized
local langCode = getLangCode()
if iconInfo.type == "ability" then
return getTranslatedName(iconInfo, langCode)
end
return iconInfo.name
end
local function render(name, args)
local originalName = name
local lowerName = name:lower()
args = args or {}
if renames[lowerName] then
lowerName = renames[lowerName]
elseif aliases[lowerName] then
lowerName = aliases[lowerName]
end
-- Lookup live data > legacy fallback
local iconInfo = iconData[lowerName] or legacyItems[lowerName]
-- Throw error if not found
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 ~= "" and args.l1 or nil
local customLink = args.link ~= "" and args.link or nil
local size = args.size or "20px"
local noLink = args["no-link"] == "true"
local noFile = args["no-file"] == "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 = getLangCode()
local displayName
if customText then
displayName = customText
elseif renames[name:lower()] then
-- Preserve original if renamed
displayName = originalName
else
displayName = getTranslatedName(iconInfo, langCode)
end
local baseLink = customLink or getLink(iconInfo, langCode)
local fragment = ""
-- Split the fragment (#Abilities) from the base link
if baseLink:find("#") then
local parts = mw.text.split(baseLink, "#", true)
baseLink = parts[1]
fragment = "#" .. (parts[2] or "")
end
local link = baseLink
if not customLink and langCode ~= "en" and baseLink ~= "" then
link = baseLink .. "/" .. langCode
end
-- Reattach fragment at the end
link = link .. fragment
-- Add CSS class for abilities
local style
if iconInfo.type == "ability" then
style = 'class="module-icon-ability" style="position:relative; bottom:2px;"'
else
style = 'class="c-icon" style="position:relative; bottom:2px;"'
end
local imageLink = noLink and "" or link
local iconHtml = ""
if not noFile then
local image = getImage(iconInfo, args)
iconHtml = string.format('<span %s>[[File:%s|%s|link=%s]]</span>', style, image, size, imageLink)
end
if iconOnly or displayName == "" then
return iconHtml
end
local textHtml = (noLink or link == "") and displayName or string.format('[[%s|%s]]', link, displayName)
if iconHtml ~= "" then
return '<span style="white-space:nowrap;">' .. iconHtml .. " " .. textHtml .. '</span>'
else
return textHtml
end
end
-- Template entrypoint
function p.render(frame)
local args = frame:getParent().args
local name = args[1] or ""
return render(name, args)
end
-- Module entrypoint
function p._render(name, args)
return render(name, args)
end
return p