Module:Icon: Difference between revisions

LVL (talk | contribs)
Made icons have a link.
LVL (talk | contribs)
Refactor to use HeroData.json, AbilityData.json, and ItemData.jsonm; no more need for hardcoded data table; auto-detect icon types
Line 1: Line 1:
local p = {}
local p = {}


-- Load icon data and language codes
-- Load language codes
local iconData = require("Module:Icon/data")
local lang_codes = mw.loadJsonData("Data:LangCodes.json")
local lang_codes = mw.loadJsonData("Data:LangCodes.json")


-- Per-page cache
-- Cache for compiled icon data (persists during page render)
local iconDataCache = nil
local cachedLangCode, cachedLangData
local cachedLangCode, cachedLangData


-- Get icon data by name
-- Build unified lookup table from bot-uploaded JSONs
local function buildIconData()
    if iconDataCache then
        return iconDataCache
    end
   
    local lookup = {}
   
    -- Load bot data
    local heroData = mw.loadJsonData("Data:HeroData.json")
    local abilityData = mw.loadJsonData("Data:AbilityData.json")
    local itemData = mw.loadJsonData("Data:ItemData.json")
   
    -- 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()
           
            lookup[lowerName] = {
                name = name,
                key = heroKey,
                link = name,
                image = name .. ".png",
                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 -- Use name from hero data if available
                        }
                    end
                end
            end
        end
    end
   
    -- Process Abilities
    for abilityKey, ability in pairs(abilityData) do
        if type(ability) == "table" and ability.Name then
            local name = ability.Name
            local lowerName = name:lower()
            local parentInfo = abilityToHero[abilityKey]
           
            -- Determine link (fallback to ability name if no parent found)
            local link = parentInfo and parentInfo.heroName or name
           
            lookup[lowerName] = {
                name = name,
                key = abilityKey,
                link = link,
                image = name .. ".png",
                type = "ability",
                class = "theme"  -- Abilities get theme class by default
            }
        end
    end
   
    -- Process Items
    for itemKey, item in pairs(itemData) do
        if type(item) == "table" and item.Name then
            local name = item.Name
            local lowerName = name:lower()
           
            lookup[lowerName] = {
                name = name,
                key = itemKey,
                link = name,
                image = name .. ".png",
                type = "item"
            }
        end
    end
   
    iconDataCache = lookup
    return lookup
end
 
-- Get icon data by name (with alias support)
local function getIconData(iconName)
local function getIconData(iconName)
     local entry = iconData[iconName:lower()]
     local data = buildIconData()
     if entry then
    local lowerName = iconName:lower()
         return entry, nil
   
    -- Check main lookup
    if data[lowerName] then
        return data[lowerName], nil
    end
   
    -- Check aliases (for edge cases like "doorman" -> "the doorman")
    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 nil, string.format("[[:Category:Module:Icon ERROR|Icon not found]] ('%s'). [[Category:Module:Icon ERROR]]", iconName)
     return nil, string.format("[[:Category:Module:Icon ERROR|Icon not found]] ('%s'). [[Category:Module:Icon ERROR]]", iconName)
end
end


-- Get cached or loaded language code and JSON data
-- Language handling
local function getLangData()
local function getLangData()
     if cachedLangData then
     if cachedLangData then
Line 49: Line 152:
     local customText = args.l1 or ""
     local customText = args.l1 or ""
      
      
     -- 1. Set Defaults from named arguments
     -- Set Defaults
     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 iconOnly = args["icon-only"] == "true"
     local iconOnly = args["icon-only"] == "true"


     -- 2. Scan unnamed parameters (2, 3, 4...) for flags and size
     -- Scan unnamed parameters
    -- This allows: {{HeroIcon|Name|icon-only|no-link}} or {{HeroIcon|Name|40px|icon-only}}
     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) -- Clean up whitespace
             local val = mw.text.trim(v)
              
              
             if val == "icon-only" then
             if val == "icon-only" then
Line 65: Line 167:
                 noLink = true
                 noLink = true
             elseif val:match("^%d+px$") then  
             elseif val:match("^%d+px$") then  
                -- If it looks like "20px" or "40px", set the size
                 size = val
                 size = val
             end
             end
Line 71: Line 172:
     end
     end


     -- 3. Proceed with standard logic...
     -- Get icon data automatically from JSON
     local iconData, err = getIconData(name)
     local iconData, err = getIconData(name)
     if not iconData then
     if not iconData then
Line 79: Line 180:
     local langCode, langData = getLangData()
     local langCode, langData = getLangData()
      
      
     -- Determine display name with clear priority
     -- Determine display name
     local displayName = ""
     local displayName = ""
     if customText ~= "" then
     if customText ~= "" then
Line 85: Line 186:
     elseif iconData.key and langData[iconData.key] then
     elseif iconData.key and langData[iconData.key] then
         displayName = langData[iconData.key]
         displayName = langData[iconData.key]
     elseif iconData.name then
     else
         displayName = iconData.name
         displayName = iconData.name
    elseif iconOnly then
        displayName = ""
    else
        displayName = name  -- fallback to input name
     end
     end


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


     -- Style logic
     -- Style logic (only abilities get theme class by default)
     local class = iconData.class or ""
     local class = iconData.class or ""
     local extra = (class:find("invert", 1, true) and " filter:invert(1);" or "")
     local extra = (class:find("invert", 1, true) and " filter:invert(1);" or "")
Line 107: Line 204:
     end
     end


     -- 4. Generate icon HTML (with link if not disabled)
     -- Generate icon HTML
     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, iconData.image, size, imageLink)
     local iconHtml = string.format('<span %s>[[File:%s|%s|link=%s]]</span>', style, iconData.image, size, imageLink)