Zum Inhalt springen

Modul:Item

Aus Firestone Idle Rpg Wiki

Die Dokumentation für dieses Modul kann unter Modul:Item/Doku erstellt werden

-- Modul:Item – Firestone-Version
--
-- Bietet (für andere Vorlagen):
--   #invoke:Item|title|key       -> "Gold"
--   #invoke:Item|short|key       -> Kurzname oder Titel
--   #invoke:Item|desc|key        -> Beschreibung (describe/description)
--   #invoke:Item|img|key         -> Bild-Basename oder '' (wenn kein Bild)
--   #invoke:Item|link|key        -> Seitentitel, z.B. "Währung#Gold" oder "Blob"
--   #invoke:Item|tooltip|key|... -> fertige Tooltip-Ausgabe (Label über |label=)
--
-- Datengrundlage: [[Modul:Item/Data]]

local p    = {}
local DATA = mw.loadData( 'Modul:Item/Data' )

local ustr = mw.ustring
local text = mw.text

-- =========================
-- Konfiguration
-- =========================

local DEFAULT_404_LINK    = 'Modul:Item/Data'
local DEFAULT_TOOLTIP_MAX = 140

-- =========================
-- Helpers
-- =========================

local function normalizeKey( name )
    if not name then
        return nil
    end
    local s = ustr.lower( tostring( name ) )
    s = s:gsub( '%s+', '' )
    return s
end

local function clone( tbl )
    local copy = {}
    for k, v in pairs( tbl or {} ) do
        copy[k] = v
    end
    return copy
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
    end
    return capitalize( item.key )
end

local function getShort( item )
    if item.short and item.short ~= '' then
        return item.short
    end
    return getTitle( item )
end

local function imgPngExists( imgname )
    if type( imgname ) == 'string' and #imgname ~= 0 then
        local t = mw.title.new( 'Datei:' .. imgname .. '.png' )
        return t and t.file and t.file.exists or false
    end
    return false
end

-- Fallback-Objekt nur für "kaputte" Aufrufe (kein Key o.ä.)
local function object404( raw )
    raw = tostring( raw or '?' )
    return {
        key      = '404',
        title    = 'ERROR: ' .. raw,
        link     = DEFAULT_404_LINK,
        img      = nil,   -- kein 404-Icon mehr
        describe = '',
    }
end

-- Holt Item aus DATA oder baut ein "virtuelles" Item,
-- wenn kein Eintrag existiert (z.B. {{Icon|blob}}).
local function getItem( raw )
    local key = normalizeKey( raw or '' )
    if not key or key == '' then
        return object404( raw )
    end

    local base = DATA[key]
    if base then
        local item = clone( base )
        item.key = key
        return item
    end

    -- virtuelles Item: nur Titel/Link aus dem Key ableiten, kein Bild
    local title = capitalize( key )
    return {
        key      = key,
        title    = title,
        link     = title2link( title ),
        img      = nil,
        describe = '',
    }
end

-- Link-Ziel für [[…]]
local function getLinkTarget( item )
    if item.link and item.link ~= '' then
        return item.link
    end
    return title2link( getTitle( item ) )
end

-- Liefert Bild-Basename oder '' wenn keins gefunden wird.
local function getImage( item )
    -- explizit in Data definiert?
    if item.img and imgPngExists( item.img ) then
        return item.img
    end

    -- Versuch: aus Titel raten (z.B. Gold -> Gold.png)
    local guess = title2link( getTitle( item ) )
    if imgPngExists( guess ) then
        return guess
    end

    -- kein Bild → leer zurückgeben, KEIN 404
    return ''
end

-- ---------- Markup → Plaintext (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 [url Label]
    str = str:gsub( '%[[^%s%]]+%s+([^%]]+)%]', '%1' )

    -- Hervorhebungen
    str = str:gsub( "''+", '' )

    -- Templates {{...}}
    str = str:gsub( '{{.-}}', '' )

    -- HTML-Tags
    str = str:gsub( '<.->', '' )

    -- Whitespace
    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 or 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 ----------

local function buildTooltip( item, opts )
    opts = opts or {}
    local max   = opts.max or DEFAULT_TOOLTIP_MAX
    local label = opts.label

    local title     = getTitle( item )
    local desc      = item.describe or item.description or ''
    local shortDesc = shorten( desc, max )
    local img       = getImage( item )

    local out = {}

    table.insert( out, '<span class="fs-tip">' )

    -- sichtbares Label
    if label and label ~= '' then
        table.insert( out, label )
    else
        local target = getLinkTarget( item )
        table.insert( out, '[[' .. target .. '|' .. title .. ']]' )
    end

    table.insert( out, '<span class="content">' )
	table.insert( out, '<span class="box">' )
    if img and img ~= '' then
        table.insert( out, '[[Datei:' .. img .. '.png|48x48px]] ' )
    end
    table.insert( out, '<span class="text">' )
    table.insert( out, '<span class="title">' )
    table.insert( out, title )
    table.insert( out, '</span>' ) -- title

    if shortDesc ~= '' then
        table.insert( out, '<span class="desc">' )
        table.insert( out, shortDesc )
        table.insert( out, '</span>' )
    end

    table.insert( out, '</span></span></span>' ) -- text + title + desc
    table.insert( out, '</span>' ) -- fs-tip

    return table.concat( out )
end

-- ---------- Frame-Args ----------

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
-- =========================

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 getShort( item )
end

function p.desc( frame )
    local key  = select( 1, getArgKey( frame ) )
    local item = getItem( key )
    return item.describe or item.description or '-'
end

function p.img( frame )
    local key  = select( 1, getArgKey( frame ) )
    local item = getItem( key )
    -- Basename oder '' zurückgeben
    return getImage( item ) or ''
end

function p.link( frame )
    local key  = select( 1, getArgKey( frame ) )
    local item = getItem( key )
    -- Nur das Seitentarget, z.B. "Währung#Gold" oder "Blob"
    return getLinkTarget( item )
end

function p.tooltip( frame )
    local key, args = getArgKey( frame )
    local item      = getItem( key )
    local max       = tonumber( args.max or args.len or args.limit ) or DEFAULT_TOOLTIP_MAX
    local label     = args.label
    return buildTooltip( item, { max = max, label = label } )
end

return p