Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Provides rendering functions for icons and icon-based UI components.

This is a WIP!


local Icon = {}

local DEFAULT_SIZE = "22"

--- @class IconArgs
--- @field icon string  File name of the icon
--- @field text string  Label rendered after the icon (may be empty)
--- @field link string  Link target for the label (may be empty)
--- @field size string  Pixel size for the icon image

--- Render a styled error message for inline display.
---
--- @param msg string  Full error message text (include any module prefix)
--- @return string  Wikitext of the styled error message
function Icon.renderError(msg)
    return '<span class="error" style="color:red;">' .. msg .. '</span>'
end

--- Normalize raw args into a table, or return an error wikitext.
---
--- @param icon string  File name of the icon
--- @param text string  Label text
--- @param link string  Link target; URL or wiki page name
--- @param size string  Pixel size; falls back to DEFAULT_SIZE if empty
--- @return IconArgs|nil  Cleaned args, or nil if validation fails
--- @return string|nil  Error wikitext if validation failed
local function normalizeArgs(icon, text, link, size)
    local trim = mw.text.trim
    icon = trim(icon or "")
    if icon == "" then
        return nil, Icon.renderError("Module:Icon: missing icon")
    end
    size = trim(size or "")
    if size == "" then size = DEFAULT_SIZE end
    return {
        icon = icon,
        text = trim(text or ""),
        link = trim(link or ""),
        size = size,
    }
end

--- Wrap text in an internal or external wiki link.
--- Returns text unchanged if link or text is empty.
---
--- @param link string  Link target; URL for external, page name for internal
--- @param text string  Display text for the link
--- @return string  Wikitext link, or plain text if link or text is empty
local function wrapLink(link, text)
    if link == "" or text == "" then return text end
    if link:match("^%w+://") or link:sub(1, 2) == "//" then
        return "[" .. link .. " " .. text .. "]"
    end
    return "[[" .. link .. "|" .. text .. "]]"
end

--- Render an icon with optional trailing text.
---
--- @param icon string  File name of the icon
--- @param text string  Text to display after the icon (pass empty string if none)
--- @param link string  Link target for the text; URL for external, 
---                     page name for internal, empty for no link
--- @param size string|number  Size of the icon in pixels
--- @return string  Wikitext for the icon followed by text
function Icon.buildIcon(icon, text, link, size)
    local args, err = normalizeArgs(icon, text, link, size)
    if err then return err end
    return "[[File:" .. args.icon .. "|" .. args.size .. "px|link=]]"
        .. wrapLink(args.link, args.text)
end

--- Entry point for: {{#invoke:Icon|main|...}}
function Icon.main(frame)
    local args = frame.args
    return Icon.buildIcon(args.icon, args.text, args.link, args.size)
end

return Icon