Module:Sandbox/LVL: Difference between revisionsGive feedback
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local | -- Single pre-indexed lookup, built by the bot at deploy time. | ||
local | -- mw.loadJsonData re-parses JSON on every page render, but is still | ||
-- dramatically faster than loading 3 separate files and iterating them. | |||
local iconData = mw.loadJsonData("Data:Sandbox") | |||
local lang_codes = mw.loadJsonData("Data:LangCodes.json") | |||
local | local cachedLangCode, cachedLangData | ||
local linkOverrides = { | |||
["Bullet Lifesteal"] = "Bullet Lifesteal (item)", | |||
["Spirit Lifesteal"] = "Spirit Lifesteal (item)" | |||
} | |||
local | local aliases = { | ||
["doorman"] = "the doorman", | |||
["mo and krill"] = "mo & krill", | |||
["mo"] = "mo & krill", | |||
["krill"] = "mo & krill", | |||
["curse"] = "cursed relic", | |||
["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", | |||
["kudzu connection"] = "watcher's covenant" | |||
} | |||
local function getLangData() | |||
local function | if cachedLangData then | ||
if | return cachedLangCode, cachedLangData | ||
return | |||
end | end | ||
local title = mw.title.getCurrentTitle().fullText | |||
local subpageLang = title:match("/([^/]+)$") | |||
local | local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en" | ||
local | |||
local langData = {} | |||
local | if langCode ~= "en" then | ||
local success, data = pcall(function() | |||
return mw.loadJsonData("Data:Lang " .. langCode .. ".json") | |||
end) | |||
end | if success and type(data) == "table" then | ||
langData = data | |||
end | end | ||
end | end | ||
cachedLangCode = langCode | |||
cachedLangData = langData | |||
return langCode, langData | |||
end | end | ||
function p.render(frame) | |||
local | local args = frame:getParent().args | ||
local | local name = args[1] or "" | ||
local lowerName = name:lower() | |||
local | |||
-- | -- Resolve aliases | ||
if aliases[lowerName] then | |||
lowerName = aliases[lowerName] | |||
if | |||
end | end | ||
-- Direct O(1) lookup, no iteration | |||
local iconInfo = iconData[lowerName] | |||
if not iconInfo then | |||
return string.format("[[:Category:Module:Icon ERROR|Icon not found]] ('%s'). [[Category:Module:Icon ERROR]]", name) | |||
end | end | ||
-- Argument parsing | |||
local | local customText = args.l1 or "" | ||
local size = args.size or "20px" | |||
local noLink = args["no-link"] == "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 | ||
end | end | ||
local | -- Language handling | ||
local langCode, langData = getLangData() | |||
local | local displayName = customText | ||
if | if displayName == "" then | ||
if iconInfo.key and langData[iconInfo.key] then | |||
displayName = langData[iconInfo.key] | |||
else | else | ||
displayName = iconInfo.name | |||
end | end | ||
end | end | ||
-- | -- Link logic | ||
local baseLink = linkOverrides[iconInfo.name] or iconInfo.link or "" | |||
local link = baseLink | |||
if langCode ~= "en" and baseLink ~= "" then | |||
local | link = baseLink .. "/" .. langCode | ||
end | end | ||
-- | -- Style logic | ||
local style | |||
if iconInfo.class and iconInfo.class:find("theme", 1, true) then | |||
style = 'class="module-icon-ability" style="position:relative; bottom:2px;"' | |||
else | |||
local | style = 'style="position:relative; bottom:2px;"' | ||
if | |||
end | end | ||
local | -- Render | ||
local imageLink = noLink and "" or link | |||
local iconHtml = string.format('<span %s>[[File:%s|%s|link=%s]]</span>', style, iconInfo.image, size, imageLink) | |||
if iconOnly or displayName == "" then | |||
return iconHtml | |||
end | end | ||
local textHtml = (noLink or link == "") and displayName or string.format('[[%s|%s]]', link, displayName) | |||
return '<span style="white-space:nowrap;">' .. iconHtml .. " " .. textHtml .. '</span>' | |||
local | |||
end | end | ||
return p | return p | ||
Revision as of 17:15, 8 March 2026
Documentation for this module may be created at Module:Sandbox/LVL/doc
local p = {}
-- Single pre-indexed lookup, built by the bot at deploy time.
-- mw.loadJsonData re-parses JSON on every page render, but is still
-- dramatically faster than loading 3 separate files and iterating them.
local iconData = mw.loadJsonData("Data:Sandbox")
local lang_codes = mw.loadJsonData("Data:LangCodes.json")
local cachedLangCode, cachedLangData
local linkOverrides = {
["Bullet Lifesteal"] = "Bullet Lifesteal (item)",
["Spirit Lifesteal"] = "Spirit Lifesteal (item)"
}
local aliases = {
["doorman"] = "the doorman",
["mo and krill"] = "mo & krill",
["mo"] = "mo & krill",
["krill"] = "mo & krill",
["curse"] = "cursed relic",
["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",
["kudzu connection"] = "watcher's covenant"
}
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
function p.render(frame)
local args = frame:getParent().args
local name = args[1] or ""
local lowerName = name:lower()
-- Resolve aliases
if aliases[lowerName] then
lowerName = aliases[lowerName]
end
-- Direct O(1) lookup, no iteration
local iconInfo = iconData[lowerName]
if not iconInfo then
return string.format("[[:Category:Module:Icon ERROR|Icon not found]] ('%s'). [[Category:Module:Icon ERROR]]", name)
end
-- Argument parsing
local customText = args.l1 or ""
local size = args.size or "20px"
local noLink = args["no-link"] == "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
-- Language handling
local langCode, langData = getLangData()
local displayName = customText
if displayName == "" then
if iconInfo.key and langData[iconInfo.key] then
displayName = langData[iconInfo.key]
else
displayName = iconInfo.name
end
end
-- Link logic
local baseLink = linkOverrides[iconInfo.name] or iconInfo.link or ""
local link = baseLink
if langCode ~= "en" and baseLink ~= "" then
link = baseLink .. "/" .. langCode
end
-- Style logic
local style
if iconInfo.class and iconInfo.class:find("theme", 1, true) then
style = 'class="module-icon-ability" style="position:relative; bottom:2px;"'
else
style = 'style="position:relative; bottom:2px;"'
end
-- Render
local imageLink = noLink and "" or link
local iconHtml = string.format('<span %s>[[File:%s|%s|link=%s]]</span>', style, iconInfo.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