Editing Module:Icon

Warning: You are not logged in. Once you make an edit, a temporary account will be created for you. Learn more. Log in or create an account to continue receiving notifications after this account expires, and to access other features.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision Your text
Line 1: Line 1:
local p = {}
local p = {}


local iconDataRaw = mw.loadJsonData("Data:ResourceLookup.json")
-- Load language codes
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
-- Cache for compiled icon data (persists during page render)
local iconDataCache = nil
local cachedLangCode, cachedLangData


local linkOverrides = table_data.linkOverrides
-- Cache for expensive existence checks (persists during page render)
local legacyItems = table_data.legacyItems
local existenceCache = {}
local missingImageOverrides = table_data.missingImageOverrides
local aliases = table_data.aliases
local renames = table_data.renames


local function getLangCode()
-- Heroes/Items that don't have images uploaded yet
     if cachedLangCode then
local missingImageOverrides = {
        return cachedLangCode
     -- Unreleased Heroes
     end
    ["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",
    -- Add any others that show red links
}


    local title = mw.title.getCurrentTitle().fullText
-- Build unified lookup table from bot-uploaded JSONs
    local subpageLang = title:match("/([^/]+)$")
local function buildIconData()
    local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en"
     if iconDataCache then
 
         return iconDataCache
    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
     end
 
   
     return missingImageOverrides[lowerName] or (iconInfo.name .. ".png")
    local lookup = {}
end
   
 
    -- Load bot data
-- Get the translated name
    local heroData = mw.loadJsonData("Data:HeroData.json")
local function getTranslatedName(iconInfo, langCode)
    local abilityData = mw.loadJsonData("Data:AbilityData.json")
    if langCode == "en" then
    local itemData = mw.loadJsonData("Data:ItemData.json")
        return iconInfo.name
   
    -- Track which hero owns which ability (for linking)
    local abilityToHero = {}
   
    -- Process Heroes
     for heroKey, hero in pairs(heroData) do
        if type(hero) == "table" and hero.Name then
            local name = hero.Name
            local lowerName = name:lower()
           
            -- Check for missing image override
            local imageName = missingImageOverrides[lowerName] or (name .. ".png")
           
            lookup[lowerName] = {
                name = name,
                key = heroKey,
                link = name,
                image = imageName,
                type = "hero"
            }
           
            -- Map abilities to parent hero
            if hero.BoundAbilities then
                for slot, ability in pairs(hero.BoundAbilities) do
                    if ability.Key then
                        abilityToHero[ability.Key] = {
                            heroName = name,
                            abilityName = ability.Name
                        }
                    end
                end
            end
        end
     end
     end
 
   
    -- 1. Direct key
-- Process Abilities
     if iconInfo.key and iconInfo.key ~= "" then
     for abilityKey, ability in pairs(abilityData) do
        local translated = lang_module.get_string(iconInfo.key, langCode, iconInfo.name
        if type(ability) == "table" and ability.Name then
        )
            local name = ability.Name
 
            local lowerName = name:lower()
        if type(translated) == "string" then
            local parentInfo = abilityToHero[abilityKey]
            return (translated:gsub("<[^>]+>", ""))
           
            -- If we already have this ability name, prefer the one linked to a hero
            if lookup[lowerName] and lookup[lowerName].type == "ability" then
                local existingHasParent = lookup[lowerName].link ~= lookup[lowerName].name
                local newHasParent = parentInfo ~= nil
               
                -- Skip if existing is linked to hero but this one isn't (prevents orphans from overwriting real ones)
                if existingHasParent and not newHasParent then
                    -- Skip this orphan ability
                else
                    -- Overwrite: new has parent and existing doesn't, or both/neither have parents
                    local link = parentInfo and parentInfo.heroName or name
                    lookup[lowerName] = {
                        name = name,
                        key = abilityKey,
                        link = link,
                        image = name .. ".png",
                        type = "ability",
                        class = "theme"
                    }
                end
            else
                -- No existing entry, add normally
                local link = parentInfo and parentInfo.heroName or name
                lookup[lowerName] = {
                    name = name,
                    key = abilityKey,
                    link = link,
                    image = name .. ".png",
                    type = "ability",
                    class = "theme"
                }
            end
         end
         end
        return iconInfo.name
     end
     end
 
   
     -- 2. Dictionary lookup
     -- Process Items
     if iconInfo.key_dictionary and iconInfo.key_dictionary ~= "" then
     for itemKey, item in pairs(itemData) do
        local entry = dictionary[iconInfo.key_dictionary]
        if type(item) == "table" and item.Name then
 
            local name = item.Name
        if type(entry) == "table" then
            local lowerName = name:lower()
             return entry[langCode]
              
                 or entry.en
            lookup[lowerName] = {
                 or iconInfo.name
                 name = name,
                key = itemKey,
                link = name,
                image = name .. ".png",
                 type = "item"
            }
         end
         end
     end
     end
 
   
     -- No valid key > fallback
     iconDataCache = lookup
     return iconInfo.name
     return lookup
end
end


-- Infer link from type and available fields
-- Get icon data by name (with alias support)
local function getLink(iconInfo, langCode)
local function getIconData(iconName)
     if iconInfo.type == "ability" then
     local data = buildIconData()
         local hero = iconInfo.hero_name or iconInfo.name
    local lowerName = iconName:lower()
       
   
        -- Get the translated name for the specific ability
    -- Check main lookup
         local abilityName = getTranslatedName(iconInfo, langCode)
    if data[lowerName] then
          
         return data[lowerName], nil
         -- Format for URL: replace spaces with underscores
    end
         local anchor = abilityName:gsub(" ", "_")
   
          
    -- Check aliases (for edge cases like "doorman" -> "the doorman")
         return hero .. "#" .. anchor
    local aliases = {
         ["doorman"] = "the doorman",
         ["mo and krill"] = "mo & krill",
         ["mo"] = "mo & krill",
         ["krill"] = "mo & krill",
        ["curse"] = "cursed relic",
         ["debuff remover"] = "dispel magic"
    }
   
    if aliases[lowerName] then
         return data[aliases[lowerName]], nil
     end
     end
 
   
     return linkOverrides[iconInfo.name] or iconInfo.name
     return nil, string.format("[[:Category:Module:Icon ERROR|Icon not found]] ('%s'). [[Category:Module:Icon ERROR]]", iconName)
end
end


-- Returns the canonical display name for a given user input
-- Language handling
-- Used by templates to store the correct casing in data attributes
local function getLangData()
-- Normalizes casing so exact string matches work reliably in Lua modules
     if cachedLangData then
function p.getCanonicalName(frame)
         return cachedLangCode, cachedLangData
    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 iconInfo = iconData[lowerName] or legacyItems[lowerName]
     local title = mw.title.getCurrentTitle().fullText
    local subpageLang = title:match("/([^/]+)$")
    local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en"


     -- If unknown, return original input
     local langData = {}
    if not iconInfo then
    if langCode ~= "en" then
         return name
        local success, data = pcall(function()
            return mw.loadJsonData("Data:Lang " .. langCode .. ".json")
        end)
        if success and type(data) == "table" then
            langData = data
         end
     end
     end


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


     return iconInfo.name
     return langCode, langData
end
end


local function render(name, args)
-- Main render function
     local originalName = name
function p.render(frame)
    local lowerName = name:lower()
     local args = frame:getParent().args
    args = args or {}
     local name = args[1] or ""
 
     local customText = args.l1 or ""
    if renames[lowerName] then
      
        lowerName = renames[lowerName]
    -- Set Defaults
    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"


    -- Scan unnamed parameters
     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 170: Line 213:
     end
     end


     local langCode = getLangCode()
    -- Get icon data automatically from JSON
     local iconData, err = getIconData(name)
    if not iconData then
        return "Error: " .. err
    end


     local displayName
    local langCode, langData = getLangData()
     if customText then
   
    -- Determine display name
     local displayName = ""
     if customText ~= "" then
         displayName = customText
         displayName = customText
     elseif renames[name:lower()] then
     elseif iconData.key and langData[iconData.key] then
        -- Preserve original if renamed
         displayName = langData[iconData.key]
         displayName = originalName
     else
     else
         displayName = getTranslatedName(iconInfo, langCode)
         displayName = iconData.name
    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


    -- Localize link if on translated subpage
    local baseLink = iconData.link or ""
     local link = baseLink
     local link = baseLink
 
   
     if not customLink and langCode ~= "en" and baseLink ~= "" then
     if langCode ~= "en" and baseLink ~= "" then
         link = baseLink .. "/" .. langCode
         link = baseLink .. "/" .. langCode
     end
     end


     -- Reattach fragment at the end
     -- Style logic (only abilities get theme class by default)
     link = link .. fragment
     local class = iconData.class or ""
 
    -- Add CSS class for abilities
     local style
     local style
     if iconInfo.type == "ability" then
     if class:find("theme", 1, true) then
         style = 'class="module-icon-ability" style="position:relative; bottom:2px;"'
         style = 'class="module-icon-ability" style="position:relative; bottom:2px;"'
     else
     else
         style = 'class="c-icon" style="position:relative; bottom:2px;"'
         style = 'style="position:relative; bottom:2px;"'
     end
     end


    -- Generate icon HTML
     local imageLink = noLink and "" or link
     local imageLink = noLink and "" or link
     local iconHtml = ""
     local iconHtml = string.format('<span %s>[[File:%s|%s|link=%s]]</span>', style, iconData.image, size, imageLink)
 
    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 222: Line 257:


     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
Please note that all contributions to The Deadlock Wiki are considered to be released under the Creative Commons Attribution-NonCommercial-ShareAlike (see Deadlock:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)
Preview page with this template

Pages included on this page: