Module:Icon: Difference between revisionsGive feedback
Fixed "Icon not found" errors for unused items by adding legacyItems fallback logic and image overrides for Bullet/Spirit Armor. |
mNo edit summary |
||
| (21 intermediate revisions by 6 users not shown) | |||
| Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local | 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 | local lang_codes = mw.loadJsonData("Data:LangCodes.json") | ||
local lang_module = require("Module:Lang") | |||
local table_data = require("Module:Icon/data") | |||
local | local cachedLangCode | ||
local | 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 | local function getLangCode() | ||
if | if cachedLangCode then | ||
return cachedLangCode | return cachedLangCode | ||
end | end | ||
| Line 56: | Line 35: | ||
local subpageLang = title:match("/([^/]+)$") | local subpageLang = title:match("/([^/]+)$") | ||
local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en" | local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en" | ||
cachedLangCode = langCode | cachedLangCode = langCode | ||
return langCode | |||
return langCode | |||
end | end | ||
-- Infer image path from name, with override support for missing images | -- Infer image path from name, with override support for missing images | ||
local function getImage(iconInfo) | local function getImage(iconInfo, args) | ||
local lowerName = iconInfo.name:lower() | local lowerName = iconInfo.name:lower() | ||
if args.image then | |||
return args.image | |||
end | |||
return missingImageOverrides[lowerName] or (iconInfo.name .. ".png") | 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 | end | ||
-- Infer link from type and available fields | -- Infer link from type and available fields | ||
local function getLink(iconInfo) | local function getLink(iconInfo, langCode) | ||
if iconInfo.type == "ability" then | 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 | end | ||
return linkOverrides[iconInfo.name] or iconInfo.name | return linkOverrides[iconInfo.name] or iconInfo.name | ||
end | end | ||
function p. | -- Returns the canonical display name for a given user input | ||
local | -- 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() | local lowerName = name:lower() | ||
if aliases[lowerName] then | if renames[lowerName] then | ||
lowerName = renames[lowerName] | |||
elseif aliases[lowerName] then | |||
lowerName = aliases[lowerName] | lowerName = aliases[lowerName] | ||
end | end | ||
local iconInfo = iconData[lowerName] or legacyItems[lowerName] | |||
local iconInfo = iconData[lowerName] | |||
-- If unknown, return original input | |||
-- | |||
if not iconInfo then | if not iconInfo then | ||
return name | |||
end | 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 | if not iconInfo then | ||
return string.format("[[:Category:Module:Icon ERROR|Icon not found]] ('%s'). [[Category:Module:Icon ERROR]]", name) | return string.format("[[:Category:Module:Icon ERROR|Icon not found]] ('%s'). [[Category:Module:Icon ERROR]]", name) | ||
end | end | ||
local customText = args.l1 or "" | 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" | ||
| Line 116: | Line 160: | ||
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 | iconOnly = true | ||
elseif val:match("^%d+px$") then size = val end | elseif val == "no-link" then | ||
noLink = true | |||
elseif val:match("^%d+px$") then | |||
size = val | |||
end | |||
end | end | ||
end | end | ||
local langCode | local langCode = getLangCode() | ||
local displayName = customText | local displayName | ||
if displayName == "" then | 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 | end | ||
local link = baseLink | local link = baseLink | ||
if langCode ~= "en" and baseLink ~= "" then | |||
if not customLink and langCode ~= "en" and baseLink ~= "" then | |||
link = baseLink .. "/" .. langCode | link = baseLink .. "/" .. langCode | ||
end | end | ||
-- | -- Reattach fragment at the end | ||
link = link .. fragment | |||
-- Add CSS class for abilities | |||
local style | local style | ||
if iconInfo.type == "ability" then | 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 | ||
style = 'style="position:relative; bottom:2px;"' | style = 'class="c-icon" style="position:relative; bottom:2px;"' | ||
end | end | ||
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, image, size, imageLink) | 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 | if iconOnly or displayName == "" then | ||
| Line 156: | Line 222: | ||
local textHtml = (noLink or link == "") and displayName or string.format('[[%s|%s]]', link, displayName) | local textHtml = (noLink or link == "") and displayName or string.format('[[%s|%s]]', link, displayName) | ||
return '<span style="white-space:nowrap;">' .. iconHtml .. " " .. textHtml .. '</span>' | |||
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 | end | ||
return p | return p | ||