Module:Icon: Difference between revisions

Jump to navigation Jump to search
mNo edit summary
Added resourcelookup2.json, table_data, dictionary/rename support, localized anchor, and 2 additional parameters.
Line 1: Line 1:
local p = {}
local p = {}


local iconData = mw.loadJsonData("Data:ResourceLookup.json")
local iconDataRaw = mw.loadJsonData("Data:ResourceLookup.json")
local lang_codes = mw.loadJsonData("Data:LangCodes.json")
local iconData2 = mw.loadJsonData("Data:ResourceLookup2.json")
local lang_module = require('Module:Lang')
local dictionary = mw.loadJsonData("Data:Dictionary")
 
local iconData = {}


local cachedLangCode
for k, v in pairs(iconDataRaw) do
    iconData[k] = v
end


local linkOverrides = {
for k, v in pairs(iconData2) do
    ["Bullet Lifesteal"] = "Bullet Lifesteal (item)",
     iconData[k] = v
     ["Spirit Lifesteal"] = "Spirit Lifesteal (item)"
end
}


local legacyItems = {
local lang_codes = mw.loadJsonData("Data:LangCodes.json")
    ["ammo scavenger"] = { name = "Ammo Scavenger", type = "item" },
local lang_module = require("Module:Lang")
    ["enduring spirit"] = { name = "Enduring Spirit", type = "item" },
local table_data = require("Module:IconSandbox/data")
    ["bullet armor"]    = { name = "Bullet Armor", type = "item" },
    ["spirit armor"]    = { name = "Spirit Armor", type = "item" },
    ["soul explosion"]  = { name = "Soul Explosion", type = "item" },
    ["soul rebirth"]    = { name = "Soul Rebirth", type = "item" },
}


local missingImageOverrides = {
local cachedLangCode
    ["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",
    ["bullet armor"] = "Bullet Armor (item).png",
    ["spirit armor"] = "Spirit Armor (item).png",
}


local aliases = {
local linkOverrides = table_data.linkOverrides
    ["doorman"] = "the doorman",
local legacyItems = table_data.legacyItems
    ["mo and krill"] = "mo & krill",
local missingImageOverrides = table_data.missingImageOverrides
    ["mo"] = "mo & krill",
local aliases = table_data.aliases
    ["krill"] = "mo & krill",
local renames = table_data.renames
    ["curse"] = "cursed relic",
    ["improved bullet armor"] = "bullet resilience",
    ["debuff remover"] = "dispel magic",
    ["defend and fight!"] = "plot armor",
    ["conjure dragon"] = "bookwyrm",
    ["backstabber"] = "stalker",
    ["flying strike"] = "flying slash",
    ["tornado"] = "dust devil",
    ["kudzu bomb"] = "entangling thorns",
    ["shadow explosion"] = "shadow transformation",
    ["watcher's covenant"] = "kudzu connection"
}


local function getLangCode()
local function getLangCode()
Line 66: Line 41:


-- 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
-- Build localized anchor (#Abilities)
local function getLocalizedAnchor(key, fallback, langCode)
    local anchor = fallback
    if langCode ~= "en" and key then
        local translated = lang_module.get_string(key, langCode, fallback)
        if type(translated) == "string" then
            anchor = translated:gsub("<[^>]+>", "")
        end
    end
    anchor = anchor:gsub(" ", "_")
    return anchor
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
         local hero = iconInfo.hero_name or iconInfo.name
         return hero .. "#Abilities"
        -- Data:Lang en.json
        local anchor = getLocalizedAnchor("guide_basics_abilities_header", "Abilities", langCode)
         return hero .. "#" .. anchor
     end
     end
     return linkOverrides[iconInfo.name] or iconInfo.name
     return linkOverrides[iconInfo.name] or iconInfo.name
end
end


local function getTranslatedName(iconInfo, langCode)
local function getTranslatedName(iconInfo, langCode)
     if langCode == "en" or not iconInfo.key then
     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
         return iconInfo.name
     end
     end
      
 
     local translatedName = lang_module.get_string(iconInfo.key, langCode, iconInfo.name)
     -- 2. Dictionary lookup
   
     if iconInfo.key_dictionary and iconInfo.key_dictionary ~= "" then
    if type(translatedName) == "string" then
        local entry = dictionary[iconInfo.key_dictionary]
        translatedName = translatedName:gsub("<[^>]+>", "")
 
        if type(entry) == "table" then
            return entry[langCode]
                or entry.en
                or iconInfo.name
        end
     end
     end
      
 
     return translatedName or iconInfo.name
     -- No valid key > fallback
     return iconInfo.name
end
end


-- Returns the canonical display name for a given user input.
-- Returns the canonical display name for a given user input
-- Used by templates to store the correct casing in data attributes
-- Used by templates to store the correct casing in data attributes
-- so that Lua modules which do exact string matching receive the right value.
-- Normalizes casing so exact string matches work reliably in Lua modules
function p.getCanonicalName(frame)
function p.getCanonicalName(frame)
     local name = frame.args[1] or ""
     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]
     local iconInfo = iconData[lowerName] or legacyItems[lowerName]
    if not iconInfo then
        iconInfo = legacyItems[lowerName]
    end


    -- If unknown, return original input
     if not iconInfo then
     if not iconInfo then
         return name -- fall back to original input if not found
         return name
     end
     end


Line 118: Line 134:


local function render(name, args)
local function render(name, args)
    local originalName = name
     local lowerName = name:lower()
     local lowerName = name:lower()
     args = args or {}
     args = args or {}


     if aliases[lowerName] then
     if renames[lowerName] then
        lowerName = renames[lowerName]
    elseif aliases[lowerName] then
         lowerName = aliases[lowerName]
         lowerName = aliases[lowerName]
     end
     end


     -- 1. Check live game data
     -- Lookup live data > legacy fallback
     local iconInfo = iconData[lowerName]
     local iconInfo = iconData[lowerName] or legacyItems[lowerName]
   
    -- 2. If not found, check legacy/unused items
    if not iconInfo then
        iconInfo = legacyItems[lowerName]
    end


     -- 3. If still not found, throw error
     -- 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 name
     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 146: Line 162:
         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
Line 154: Line 174:
     local langCode = getLangCode()
     local langCode = getLangCode()


     local displayName = customText
     local displayName
     if displayName == name then
    if customText then
        displayName = customText
     elseif renames[name:lower()] then
        -- Preserve original if renamed
        displayName = originalName
    else
         displayName = getTranslatedName(iconInfo, langCode)
         displayName = getTranslatedName(iconInfo, langCode)
     end
     end


     local baseLink = getLink(iconInfo)
     local baseLink = customLink or getLink(iconInfo, langCode)
     local fragment = ""
     local fragment = ""


Line 170: Line 195:


     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


     -- Re-attach the fragment at the very end
     -- Reattach fragment at the end
     link = link .. fragment
     link = link .. fragment


     -- Abilities get the module-icon-ability class for light/dark theme filter support
     -- Add CSS class for abilities
     local style
     local style
     if iconInfo.type == "ability" then
     if iconInfo.type == "ability" then
Line 185: Line 211:
     end
     end


    local image = getImage(iconInfo)
     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 194: Line 224:


     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
end


Line 207: Line 242:
-- Module entrypoint
-- Module entrypoint
function p._render(name, args)
function p._render(name, args)
return render(name, args)
    return render(name, args)
end
end


return p
return p