Modul:Item
Die Dokumentation für dieses Modul kann unter Modul:Item/Doku erstellt werden
-- Modul:Item – Firestone-Version
--
-- Nachbau von Angel-Legion „Module:Item“ mit:
-- * title – Anzeigetitel
-- * short – Kurzname (Fallback auf title)
-- * description – Beschreibung (describe)
-- * link – Seitentitel / Link
-- * img – Bild-Basename (ohne „Datei:“ / „.png“)
-- * type – Typ (z.B. "currencies", via [[Modul:Item/Type]])
-- * tooltip – fertige Tooltip-Ausgabe (Link + Icon + gekürzte Beschreibung)
--
-- Datengrundlage: [[Modul:Item/Data]]
-- Typgruppen: [[Modul:Item/Types]] + [[Modul:Item/Type]]
local p = {}
local DATA = mw.loadData('Modul:Item/Data')
local ItemType = require('Modul:Item/Type')
local ustr = mw.ustring
local text = mw.text
-- =========================
-- Konfiguration
-- =========================
-- Fallback-Link-Prefix, wenn im Datensatz weder link noch id existiert.
-- Für Firestone z.B. "Item/" oder "Ressource/". Bei Währungen ist überall link gesetzt,
-- aber wir lassen den Fallback trotzdem drin.
local DEFAULT_LINK_PREFIX = 'Item/'
-- Fallback für 404-Objekte
local DEFAULT_404_IMG = '404'
local DEFAULT_404_LINK = 'Modul:Item/Data'
local DEFAULT_404_TYPE = 'unknown'
-- Tooltip-Einstellungen
local DEFAULT_TOOLTIP_MAX = 140 -- max. Zeichen für Beschreibung im Tooltip
-- =========================
-- Hilfsfunktionen
-- =========================
local function normalizeKey(name)
if not name then
return nil
end
name = ustr.lower(tostring(name))
name = name:gsub('%s+', '')
return name
end
local function clone(tbl)
local copy = {}
for k, v in pairs(tbl or {}) do
copy[k] = v
end
return copy
end
local function object404(name)
name = tostring(name or '?')
return {
key = '404',
title = 'ERROR: ' .. name,
link = DEFAULT_404_LINK,
img = DEFAULT_404_IMG,
type = DEFAULT_404_TYPE,
describe = '',
}
end
local function getItem(raw)
local key = normalizeKey(raw or '')
if not key or key == '' then
return object404(raw)
end
local base = DATA[key]
if not base then
return object404(key)
end
local item = clone(base)
item.key = key
return item
end
local function capitalize(str)
if not str then
return ''
end
local s = string.lower(tostring(str))
return string.gsub(' ' .. s, '%W%l', string.upper):sub(2)
end
local function title2link(title)
return (tostring(title or '')):gsub('%s', '_')
end
local function getTitle(item)
if item.title and item.title ~= '' then
return item.title
elseif item.short and item.short ~= '' then
return item.short
end
return capitalize(item.key)
end
local function imgPngExists(imgname)
if type(imgname) == 'string' and #imgname ~= 0 then
-- „Datei:“ ist der deutsche Namensraum; „File:“ funktioniert oft auch.
local t = mw.title.new('Datei:' .. imgname .. '.png')
return t and t.file and t.file.exists or false
end
return false
end
local function getImage(item)
if item.img and imgPngExists(item.img) then
return item.img
end
-- Versuche, aus dem Titel einen Dateinamen zu raten
local sublink = ustr.lower(title2link(getTitle(item)))
if imgPngExists(sublink) then
return sublink
end
return object404(item.key).img
end
local function getLink(item)
if item.link and item.link ~= '' then
return item.link
end
-- Fallback: generischer Namensraum + Titel
return DEFAULT_LINK_PREFIX .. title2link(getTitle(item))
end
local function getType(item)
return ItemType.typenameForKey(item.key)
end
-- =========================
-- Markup -> Plaintext + Kürzen (für Tooltip)
-- =========================
local function stripMarkup(str)
if not str or str == '' then
return ''
end
str = tostring(str)
-- interne Links [[Seite|Label]] / [[Seite]]
str = str:gsub('%[%[([^%]|]+)|([^%]]+)%]%]', '%2')
str = str:gsub('%[%[([^%]]+)%]%]', '%1')
-- externe Links [http://url Label]
str = str:gsub('%[[^%s%]]+%s+([^%]]+)%]', '%1')
-- Hervorhebungen '' / '''
str = str:gsub("''+", '')
-- Templates {{...}} komplett entfernen
str = str:gsub('{{.-}}', '')
-- HTML-Tags <...>
str = str:gsub('<.->', '')
-- Whitespace aufräumen
str = str:gsub('%s+', ' ')
if text and text.trim then
str = text.trim(str)
end
return str
end
local function shorten(str, max)
str = stripMarkup(str)
max = tonumber(max) or 0
if max <= 0 then
return str
end
if ustr.len(str) <= max then
return str
end
local cut = ustr.sub(str, 1, max)
local lastSpace = ustr.find(cut, ' [^ ]*$')
if lastSpace and lastSpace > max * 0.6 then
cut = ustr.sub(cut, 1, lastSpace - 1)
end
return cut .. '…'
end
-- =========================
-- Tooltip-Aufbau
-- =========================
local function buildTooltip(item, opts)
opts = opts or {}
local max = opts.max or DEFAULT_TOOLTIP_MAX
local title = getTitle(item)
local desc = item.describe or item.description or ''
local shortDesc = shorten(desc, max)
local img = getImage(item)
local link = getLink(item)
local parts = {}
-- Wrapper – darauf hängt der :hover-Effekt
table.insert(parts, '<span class="kr-item-tooltip">')
-- Label oder Link
if link and link ~= '' then
table.insert(parts, '[[' .. link .. '|' .. title .. ']]')
else
table.insert(parts, title)
end
-- Tooltip-Box
table.insert(parts, '<span class="kr-item-tooltip-box">')
-- Header: Icon + Titel
table.insert(parts, '<span class="kr-item-tooltip-header">')
if img and img ~= '' then
table.insert(parts, '[[Datei:' .. img .. '.png|24x24px|class=kr-item-icon]] ')
end
table.insert(parts, '<span class="kr-item-tooltip-title">')
table.insert(parts, title)
table.insert(parts, '</span></span>') -- title + header
-- Body: Beschreibung (Plaintext, gekürzt)
if shortDesc ~= '' then
table.insert(parts, '<span class="kr-item-tooltip-body">')
table.insert(parts, shortDesc)
table.insert(parts, '</span>')
end
table.insert(parts, '</span>') -- Box
table.insert(parts, '</span>') -- Wrapper
return table.concat(parts)
end
-- =========================
-- Argument-Handling (#invoke)
-- =========================
local function extractKey(args)
if not args then
return nil
end
return args[1] or args.name or args.key or args.id or args.nameid
end
local function getArgKey(frame)
if not frame then
return nil, {}
end
local args = frame.args or {}
local key = extractKey(args)
if key and key ~= '' then
return key, args
end
if frame.getParent then
local parent = frame:getParent()
if parent and parent.args then
args = parent.args
key = extractKey(args)
if key and key ~= '' then
return key, args
end
end
end
return nil, args
end
-- =========================
-- Öffentliche Funktionen – #invoke-Schnittstelle
-- =========================
function p.title(frame)
local key = select(1, getArgKey(frame))
local item = getItem(key)
return getTitle(item)
end
function p.short(frame)
local key = select(1, getArgKey(frame))
local item = getItem(key)
return item.short or getTitle(item)
end
function p.description(frame)
local key = select(1, getArgKey(frame))
local item = getItem(key)
return item.describe or item.description or '-'
end
function p.link(frame)
local key = select(1, getArgKey(frame))
local item = getItem(key)
return getLink(item)
end
function p.img(frame)
local key = select(1, getArgKey(frame))
local item = getItem(key)
return getImage(item)
end
function p.type(frame)
local key = select(1, getArgKey(frame))
local item = getItem(key)
return getType(item)
end
-- {{#invoke:Item|tooltip|gold}}
-- Optional: {{#invoke:Item|tooltip|gold|max=200}}
function p.tooltip(frame)
local key, args = getArgKey(frame)
local item = getItem(key)
local max = args.max or args.len or args.limit
return buildTooltip(item, { max = tonumber(max) or DEFAULT_TOOLTIP_MAX })
end
return p