Module:Sandbox/LVL: Difference between revisionsGive feedback
Jump to navigation
Jump to search
No edit summary Tag: Manual revert |
No edit summary |
||
| Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
-- Load | -- Load language codes | ||
local | local lang_codes = mw.loadJsonData("Data:LangCodes.json") | ||
-- | -- Cache for compiled icon data (persists during page render) | ||
local iconDataCache = nil | |||
local cachedLangCode, cachedLangData | |||
-- 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 | end | ||
-- | -- Get icon data by name (with alias support) | ||
-- | local function getIconData(iconName) | ||
local data = buildIconData() | |||
local lowerName = iconName:lower() | |||
local | |||
if | -- Check main lookup | ||
local | 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 | |||
return nil, string.format("[[:Category:Module:Icon ERROR|Icon not found]] ('%s'). [[Category:Module:Icon ERROR]]", iconName) | |||
end | |||
-- Language handling (unchanged from your original) | |||
local function getLangData() | |||
if cachedLangData then | |||
return cachedLangCode, cachedLangData | |||
end | |||
local title = mw.title.getCurrentTitle().fullText | |||
local subpageLang = title:match("/([^/]+)$") | |||
local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en" | |||
local langData = {} | |||
if langCode ~= "en" then | |||
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 | ||
cachedLangCode = langCode | |||
cachedLangData = langData | |||
return langCode, langData | |||
end | |||
-- Main render function (updated to handle missing keys gracefully) | |||
function p.render(frame) | |||
local args = frame:getParent().args | |||
local name = args[1] or "" | |||
local customText = args.l1 or "" | |||
-- Set Defaults | |||
local size = args.size or "20px" | |||
local noLink = args["no-link"] == "true" | |||
local iconOnly = args["icon-only"] == "true" | |||
-- Scan unnamed parameters | |||
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 | |||
-- Get icon data automatically from JSON | |||
local iconData, err = getIconData(name) | |||
if not iconData then | |||
return "Error: " .. err | |||
end | |||
local langCode, langData = getLangData() | |||
-- Determine display name | |||
local displayName = "" | |||
if customText ~= "" then | |||
displayName = customText | |||
elseif iconData.key and langData[iconData.key] then | |||
displayName = langData[iconData.key] | |||
else | |||
displayName = iconData.name | |||
end | |||
-- Localize link if on translated subpage | |||
local baseLink = iconData.link or "" | |||
local link = (langCode ~= "en" and baseLink ~= "") and (baseLink .. "/" .. langCode) or baseLink | |||
-- Style logic (only abilities get theme class by default) | |||
local class = iconData.class or "" | |||
local extra = (class:find("invert", 1, true) and " filter:invert(1);" or "") | |||
local style | |||
if class:find("theme", 1, true) then | |||
style = 'class="module-icon-ability" style="position:relative; bottom:2px;' .. extra .. '"' | |||
else | |||
style = 'style="position:relative; bottom:2px;' .. extra .. '"' | |||
end | |||
-- Generate icon HTML | |||
local imageLink = noLink and "" or link | |||
local iconHtml = string.format('<span %s>[[File:%s|%s|link=%s]]</span>', style, iconData.image, size, imageLink) | |||
if iconOnly or displayName == "" then | |||
end | return iconHtml | ||
end | |||
local textHtml = (noLink or link == "") and displayName or string.format('[[%s|%s]]', link, displayName) | |||
return '<span style="white-space:nowrap;">' .. iconHtml .. " " .. textHtml .. '</span>' | |||
end | end | ||
return p | return p | ||
Revision as of 15:21, 9 February 2026
Documentation for this module may be created at Module:Sandbox/LVL/doc
local p = {}
-- Load language codes
local lang_codes = mw.loadJsonData("Data:LangCodes.json")
-- Cache for compiled icon data (persists during page render)
local iconDataCache = nil
local cachedLangCode, cachedLangData
-- 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 data = buildIconData()
local lowerName = iconName:lower()
-- 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
return nil, string.format("[[:Category:Module:Icon ERROR|Icon not found]] ('%s'). [[Category:Module:Icon ERROR]]", iconName)
end
-- Language handling (unchanged from your original)
local function getLangData()
if cachedLangData then
return cachedLangCode, cachedLangData
end
local title = mw.title.getCurrentTitle().fullText
local subpageLang = title:match("/([^/]+)$")
local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en"
local langData = {}
if langCode ~= "en" then
local success, data = pcall(function()
return mw.loadJsonData("Data:Lang " .. langCode .. ".json")
end)
if success and type(data) == "table" then
langData = data
end
end
cachedLangCode = langCode
cachedLangData = langData
return langCode, langData
end
-- Main render function (updated to handle missing keys gracefully)
function p.render(frame)
local args = frame:getParent().args
local name = args[1] or ""
local customText = args.l1 or ""
-- Set Defaults
local size = args.size or "20px"
local noLink = args["no-link"] == "true"
local iconOnly = args["icon-only"] == "true"
-- Scan unnamed parameters
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
-- Get icon data automatically from JSON
local iconData, err = getIconData(name)
if not iconData then
return "Error: " .. err
end
local langCode, langData = getLangData()
-- Determine display name
local displayName = ""
if customText ~= "" then
displayName = customText
elseif iconData.key and langData[iconData.key] then
displayName = langData[iconData.key]
else
displayName = iconData.name
end
-- Localize link if on translated subpage
local baseLink = iconData.link or ""
local link = (langCode ~= "en" and baseLink ~= "") and (baseLink .. "/" .. langCode) or baseLink
-- Style logic (only abilities get theme class by default)
local class = iconData.class or ""
local extra = (class:find("invert", 1, true) and " filter:invert(1);" or "")
local style
if class:find("theme", 1, true) then
style = 'class="module-icon-ability" style="position:relative; bottom:2px;' .. extra .. '"'
else
style = 'style="position:relative; bottom:2px;' .. extra .. '"'
end
-- Generate icon HTML
local imageLink = noLink and "" or link
local iconHtml = string.format('<span %s>[[File:%s|%s|link=%s]]</span>', style, iconData.image, size, imageLink)
if iconOnly or displayName == "" then
return iconHtml
end
local textHtml = (noLink or link == "") and displayName or string.format('[[%s|%s]]', link, displayName)
return '<span style="white-space:nowrap;">' .. iconHtml .. " " .. textHtml .. '</span>'
end
return p