Module:Icon: Difference between revisions

From The Deadlock Wiki
Jump to navigation Jump to search
New version
 
LVL (talk | contribs)
mNo edit summary
 
(47 intermediate revisions by 7 users not shown)
Line 1: Line 1:
local p = {}
local p = {}


-- Load icon data and language codes
local iconDataRaw = mw.loadJsonData("Data:ResourceLookup.json")
local iconData = require("Module:Icon/data")
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")


-- Per-page cache
local cachedLangCode
local cachedLangCode, cachedLangData


-- Get icon data by name
local linkOverrides = table_data.linkOverrides
local function getIconData(iconName)
local legacyItems = table_data.legacyItems
    return iconData[iconName:lower()], "[[Module:Icon/data|Icon not found.]] [[Category:Module:Icon ERROR]]"
local missingImageOverrides = table_data.missingImageOverrides
end
local aliases = table_data.aliases
local renames = table_data.renames


-- Get cached or loaded language code and JSON data
local function getLangCode()
local function getLangData()
     if cachedLangCode then
     if cachedLangData then
         return cachedLangCode
         return cachedLangCode, cachedLangData
     end
     end


Line 23: Line 36:
     local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en"
     local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en"


     local langData = {}
     cachedLangCode = langCode
     if langCode ~= "en" then
     return langCode
        local success, data = pcall(function()
end
            return mw.loadJsonData("Data:Lang " .. langCode .. ".json")
 
         end)
-- Infer image path from name, with override support for missing images
         if success and type(data) == "table" then
local function getImage(iconInfo, args)
             langData = data
    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
    -- 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
     end


     cachedLangCode = langCode
-- Quick hack: ability names are used by MediaWiki:Gadget-infobox-tooltip.js and expected to be localized
     cachedLangData = langData
     local langCode = getLangCode()
 
    if iconInfo.type == "ability" then
        return getTranslatedName(iconInfo, langCode)
     end


     return langCode, langData
     return iconInfo.name
end
end


-- Main render function
local function render(name, args)
function p.render(frame)
     local originalName = name
     local args = frame:getParent().args
    local lowerName = name:lower()
     local name = args[1] or ""
    args = args or {}
     local customText = args.l1 or ""
 
     local width = args.width or "20px"
    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 noLink = args["no-link"] == "true"
    local noFile = args["no-file"] == "true"
     local iconOnly = args["icon-only"] == "true"
     local iconOnly = args["icon-only"] == "true"


     local iconData, err = getIconData(name)
     for k, v in pairs(args) do
     if not iconData then
        if type(k) == "number" and k > 1 then
         return "Error: " .. err
            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 langCode, langData = getLangData()
     local baseLink = customLink or getLink(iconInfo, langCode)
     local hasOnlyImage = iconData.image and iconData.image ~= "" and not iconData.name and not iconData.key and (iconData.link == nil or iconData.link == "") and customText == ""
     local fragment = ""


     -- Use translation if available
     -- Split the fragment (#Abilities) from the base link
local displayName = (iconData.name or (not hasOnlyImage and name)) or ""
    if baseLink:find("#") then
if iconData.key and langData[iconData.key] then
        local parts = mw.text.split(baseLink, "#", true)
    displayName = langData[iconData.key]
        baseLink = parts[1]
end
        fragment = "#" .. (parts[2] or "")
    end


    -- Localize link if on a translated subpage
     local link = baseLink
    local baseLink = iconData.link or ""
     local link = (langCode ~= "en" and baseLink ~= "") and (baseLink .. "/" .. langCode) or baseLink


     -- Style logic
     if not customLink and langCode ~= "en" and baseLink ~= "" then
    local class = iconData.class or ""
         link = baseLink .. "/" .. langCode
    local style = 'style="white-space:nowrap; position:relative; bottom:2px;"'
    if class == "ability" then
         style = 'class="module-icon-ability" style="white-space:nowrap; position:relative; bottom:2px;"'
     end
     end


     local finalText = (customText ~= "") and customText or displayName
     -- Reattach fragment at the end
     local iconHtml = string.format('<span %s>[[File:%s|%s|link=]]</span>', style, iconData.image, width)
     link = link .. fragment


if iconOnly or displayName == "" then
    -- Add CSS class for abilities
    return iconHtml
    local style
end
    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


    local textHtml = (noLink or link == "") and finalText or string.format('[[%s|%s]]', link, finalText)
-- Module entrypoint
     return iconHtml .. " " .. textHtml
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.

Any of the following templates can be used. The module automatically detects the icon type:

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