| Latest revision |
Your text |
| Line 1: |
Line 1: |
| local p = {} | | local p = {} |
|
| |
|
| local iconDataRaw = mw.loadJsonData("Data:ResourceLookup.json") | | -- Load icon data and language codes |
| local iconData2 = mw.loadJsonData("Data:ResourceLookup2.json") | | local iconData = require("Module:Icon/data") |
| local dictionary = mw.loadJsonData("Data:Dictionary")
| | local lang_codes = mw.loadJsonData("Data:LangCodes.json") |
|
| |
|
| local iconData = {} | | -- Per-page cache |
| | local cachedLangCode, cachedLangData |
|
| |
|
| for k, v in pairs(iconDataRaw) do
| | -- Get icon data by name |
| iconData[k] = v | | local function getIconData(iconName) |
| | return iconData[iconName:lower()], "[[:Category:Module:Icon ERROR|Icon not found.]] [[Category:Module:Icon ERROR]]" |
| end | | end |
|
| |
|
| for k, v in pairs(iconData2) do
| | -- Get cached or loaded language code and JSON data |
| iconData[k] = v
| | local function getLangData() |
| end
| | if cachedLangData then |
| | | return cachedLangCode, cachedLangData |
| local lang_codes = mw.loadJsonData("Data:LangCodes.json")
| |
| local lang_module = require("Module:Lang")
| |
| local table_data = require("Module:Icon/data")
| |
| | |
| local cachedLangCode
| |
| | |
| local linkOverrides = table_data.linkOverrides
| |
| local legacyItems = table_data.legacyItems
| |
| local missingImageOverrides = table_data.missingImageOverrides
| |
| local aliases = table_data.aliases
| |
| local renames = table_data.renames
| |
| | |
| local function getLangCode() | |
| if cachedLangCode then | |
| return cachedLangCode | |
| end | | end |
|
| |
|
| Line 36: |
Line 23: |
| local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en" | | local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en" |
|
| |
|
| cachedLangCode = langCode | | local langData = {} |
| return langCode | | if langCode ~= "en" then |
| end
| | local success, data = pcall(function() |
| | | return mw.loadJsonData("Data:Lang " .. langCode .. ".json") |
| -- Infer image path from name, with override support for missing images
| | end) |
| local function getImage(iconInfo, args) | | if success and type(data) == "table" then |
| local lowerName = iconInfo.name:lower()
| | langData = data |
| | |
| if args.image then
| |
| return args.image
| |
| end
| |
| | |
| return missingImageOverrides[lowerName] or (iconInfo.name .. ".png")
| |
| end | |
| | |
| -- Get the translated name
| |
| local function getTranslatedName(iconInfo, langCode)
| |
| 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 | | end |
|
| |
| return iconInfo.name
| |
| end | | end |
|
| |
|
| -- 2. Dictionary lookup | | cachedLangCode = langCode |
| if iconInfo.key_dictionary and iconInfo.key_dictionary ~= "" then | | cachedLangData = langData |
| local entry = dictionary[iconInfo.key_dictionary]
| |
|
| |
|
| if type(entry) == "table" then
| | return langCode, langData |
| return entry[langCode]
| |
| or entry.en
| |
| or iconInfo.name
| |
| end
| |
| end
| |
| | |
| -- No valid key > fallback
| |
| return iconInfo.name
| |
| end | | end |
|
| |
|
| -- Infer link from type and available fields | | -- Main render function |
| local function getLink(iconInfo, langCode)
| | function p.render(frame) |
| if iconInfo.type == "ability" then
| | local args = frame:getParent().args |
| local hero = iconInfo.hero_name or iconInfo.name
| | local name = args[1] or "" |
|
| | local customText = args.l1 or "" |
| -- Get the translated name for the specific ability
| |
| local abilityName = getTranslatedName(iconInfo, langCode)
| |
|
| |
| -- Format for URL: replace spaces with underscores
| |
| local anchor = abilityName:gsub(" ", "_")
| |
|
| |
| return hero .. "#" .. anchor
| |
| end
| |
| | |
| return linkOverrides[iconInfo.name] or iconInfo.name
| |
| end
| |
| | |
| -- Returns the canonical display name for a given user input
| |
| -- Used by templates to store the correct casing in data attributes
| |
| -- Normalizes casing so exact string matches work reliably in Lua modules
| |
| function p.getCanonicalName(frame) | |
| 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
| |
| | |
| local iconInfo = iconData[lowerName] or legacyItems[lowerName]
| |
| | |
| -- If unknown, return original input
| |
| if not iconInfo then
| |
| return name
| |
| end
| |
| | |
| -- Quick hack: ability names are used by MediaWiki:Gadget-infobox-tooltip.js and expected to be localized
| |
| local langCode = getLangCode()
| |
| | |
| if iconInfo.type == "ability" then
| |
| return getTranslatedName(iconInfo, langCode)
| |
| end
| |
| | |
| return iconInfo.name
| |
| end
| |
| | |
| local function render(name, args)
| |
| local originalName = name | |
| local lowerName = name:lower()
| |
| args = args or {}
| |
| | |
| if renames[lowerName] then
| |
| lowerName = renames[lowerName]
| |
| 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" |
|
| |
|
| for k, v in pairs(args) do | | local iconData, err = getIconData(name) |
| if type(k) == "number" and k > 1 then
| | if not iconData then |
| local val = mw.text.trim(v)
| | return "Error: " .. err |
| 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
| |
| | |
| local langCode = getLangCode()
| |
| | |
| local displayName
| |
| if customText then
| |
| displayName = customText
| |
| elseif renames[name:lower()] then
| |
| -- Preserve original if renamed
| |
| displayName = originalName
| |
| else
| |
| displayName = getTranslatedName(iconInfo, langCode)
| |
| end | | end |
|
| |
|
| local baseLink = customLink or getLink(iconInfo, langCode) | | local langCode, langData = getLangData() |
| local fragment = "" | | local hasOnlyImage = iconData.image and iconData.image ~= "" and not iconData.name and not iconData.key and (iconData.link == nil or iconData.link == "") and customText == "" |
|
| |
|
| -- Split the fragment (#Abilities) from the base link | | -- Use translation if available |
| if baseLink:find("#") then
| | local displayName = (iconData.name or (not hasOnlyImage and name)) or "" |
| local parts = mw.text.split(baseLink, "#", true)
| | if iconData.key and langData[iconData.key] then |
| baseLink = parts[1]
| | displayName = langData[iconData.key] |
| fragment = "#" .. (parts[2] or "")
| | end |
| end
| |
|
| |
|
| local link = baseLink | | -- Localize link if on a translated subpage |
| | local baseLink = iconData.link or "" |
| | local link = (langCode ~= "en" and baseLink ~= "") and (baseLink .. "/" .. langCode) or baseLink |
|
| |
|
| if not customLink and langCode ~= "en" and baseLink ~= "" then | | -- Style logic |
| link = baseLink .. "/" .. langCode | | local class = iconData.class or "" |
| | local style = 'style="white-space:nowrap; position:relative; bottom:2px;"' |
| | if class == "ability" then |
| | style = 'class="module-icon-ability" style="white-space:nowrap; position:relative; bottom:2px;"' |
| end | | end |
|
| |
|
| -- Reattach fragment at the end | | local finalText = (customText ~= "") and customText or displayName |
| link = link .. fragment | | local iconHtml = string.format('<span %s>[[File:%s|%s|link=]]</span>', style, iconData.image, size) |
|
| |
|
| -- Add CSS class for abilities
| | if iconOnly or displayName == "" then |
| local style
| | return iconHtml |
| if iconInfo.type == "ability" then
| | end |
| style = 'class="module-icon-ability" style="position:relative; bottom:2px;"'
| |
| else
| |
| style = 'class="c-icon" style="position:relative; bottom:2px;"'
| |
| end
| |
| | |
| local imageLink = noLink and "" or link
| |
| 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
| |
| return iconHtml
| |
| end
| |
| | |
| local textHtml = (noLink or link == "") and displayName or string.format('[[%s|%s]]', link, displayName)
| |
| | |
| 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
| | local textHtml = (noLink or link == "") and finalText or string.format('[[%s|%s]]', link, finalText) |
| function p._render(name, args)
| | return iconHtml .. " " .. textHtml |
| return render(name, args) | |
| end | | end |
|
| |
|
| return p | | return p |