Module:Icon: Difference between revisionsGive feedback
Add placeholder image support for unreleased heroes (Boho, Druid, Fortuna, etc.) to prevent red links in navboxes |
mNo edit summary |
||
| (34 intermediate revisions by 6 users not shown) | |||
| Line 1: | Line 1: | ||
local p = {} | 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_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 | |||
end | end | ||
local title = mw.title.getCurrentTitle().fullText | |||
local subpageLang = title:match("/([^/]+)$") | |||
local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en" | |||
local | |||
local | cachedLangCode = langCode | ||
local | 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 | 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 | |||
if type( | local entry = dictionary[iconInfo.key_dictionary] | ||
if type(entry) == "table" then | |||
return entry[langCode] | |||
or entry.en | |||
or iconInfo.name | |||
end | end | ||
end | end | ||
-- No valid key > fallback | |||
return | return iconInfo.name | ||
end | end | ||
-- | -- Infer link from type and available fields | ||
local function | local function getLink(iconInfo, langCode) | ||
local | 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) | |||
return | |||
-- Format for URL: replace spaces with underscores | |||
local anchor = abilityName:gsub(" ", "_") | |||
return hero .. "#" .. anchor | |||
end | end | ||
return linkOverrides[iconInfo.name] or iconInfo.name | |||
end | end | ||
-- | -- Returns the canonical display name for a given user input | ||
local | -- Used by templates to store the correct casing in data attributes | ||
if | -- 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 | end | ||
local | local iconInfo = iconData[lowerName] or legacyItems[lowerName] | ||
-- If unknown, return original input | |||
if | 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 | 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 | |||
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" | ||
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 | if val == "icon-only" then | ||
iconOnly = true | iconOnly = true | ||
elseif val == "no-link" then | elseif val == "no-link" then | ||
noLink = true | noLink = true | ||
elseif val:match("^%d+px$") then | elseif val:match("^%d+px$") then | ||
size = val | size = val | ||
end | end | ||
| Line 189: | Line 170: | ||
end | end | ||
local langCode = getLangCode() | |||
local | |||
local displayName | |||
if customText then | |||
local displayName | |||
if customText | |||
displayName = customText | displayName = customText | ||
elseif | elseif renames[name:lower()] then | ||
displayName = | -- Preserve original if renamed | ||
displayName = originalName | |||
else | else | ||
displayName = | 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 = | |||
-- | 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 | 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 | ||
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, | 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 230: | 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 | ||