Modul:Item: Unterschied zwischen den Versionen
Keine Bearbeitungszusammenfassung |
Keine Bearbeitungszusammenfassung |
||
| (7 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
-- Modul:Item – Firestone-Version | -- 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]] | -- Datengrundlage: [[Modul:Item/Data]] | ||
local p | local p = {} | ||
local DATA | local DATA = mw.loadData( 'Modul:Item/Data' ) | ||
local ustr | local ustr = mw.ustring | ||
local text | local text = mw.text | ||
-- ========================= | -- ========================= | ||
| Zeile 26: | Zeile 21: | ||
-- ========================= | -- ========================= | ||
local DEFAULT_404_LINK = 'Modul:Item/Data' | |||
local DEFAULT_404_LINK | local DEFAULT_TOOLTIP_MAX = 140 | ||
local DEFAULT_TOOLTIP_MAX | |||
-- ========================= | -- ========================= | ||
| Zeile 40: | Zeile 28: | ||
-- ========================= | -- ========================= | ||
local function normalizeKey(name) | local function normalizeKey( name ) | ||
if not name then | if not name then | ||
return nil | return nil | ||
end | end | ||
local s = ustr.lower(tostring(name)) | local s = ustr.lower( tostring( name ) ) | ||
s = s:gsub('%s+', '') | s = s:gsub( '%s+', '' ) | ||
return s | return s | ||
end | end | ||
local function clone(tbl) | local function clone( tbl ) | ||
local copy = {} | local copy = {} | ||
for k, v in pairs(tbl or {}) do | for k, v in pairs( tbl or {} ) do | ||
copy[k] = v | copy[k] = v | ||
end | end | ||
| Zeile 57: | Zeile 45: | ||
end | end | ||
local function capitalize( str ) | |||
local function capitalize(str) | |||
if not str then | if not str then | ||
return '' | return '' | ||
end | end | ||
local s = string.lower(tostring(str)) | local s = string.lower( tostring( str ) ) | ||
return string.gsub(' ' .. s, '%W%l', string.upper):sub(2) | return string.gsub( ' ' .. s, '%W%l', string.upper ):sub( 2 ) | ||
end | end | ||
local function title2link(title) | local function title2link( title ) | ||
return (tostring(title or '')):gsub('%s', '_') | return ( tostring( title or '' ) ):gsub( '%s', '_' ) | ||
end | end | ||
local function getTitle(item) | local function getTitle( item ) | ||
if item.title and item.title ~= '' then | if item.title and item.title ~= '' then | ||
return item.title | return item.title | ||
end | end | ||
return capitalize(item.key) | return capitalize( item.key ) | ||
end | end | ||
local function imgPngExists(imgname) | local function getShort( item ) | ||
if type(imgname) == 'string' and #imgname ~= 0 then | if item.short and item.short ~= '' then | ||
local t = mw.title.new('Datei:' .. imgname .. '.png') | 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 | return t and t.file and t.file.exists or false | ||
end | end | ||
| Zeile 112: | Zeile 79: | ||
end | end | ||
local function | -- Fallback-Objekt nur für "kaputte" Aufrufe (kein Key o.ä.) | ||
local function object404( raw ) | |||
return | 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 | end | ||
local | local base = DATA[key] | ||
if | if base then | ||
return | local item = clone( base ) | ||
item.key = key | |||
return item | |||
end | end | ||
return | -- 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 | end | ||
local function getLinkTarget(item) | -- Link-Ziel für [[…]] | ||
local function getLinkTarget( item ) | |||
if item.link and item.link ~= '' then | if item.link and item.link ~= '' then | ||
return item.link | return item.link | ||
end | end | ||
return title2link(getTitle(item)) | return title2link( getTitle( item ) ) | ||
end | end | ||
local function | -- Liefert Bild-Basename oder '' wenn keins gefunden wird. | ||
local function getImage( item ) | |||
local | -- explizit in Data definiert? | ||
if | if item.img and imgPngExists( item.img ) then | ||
return | 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 | end | ||
return | |||
-- kein Bild → leer zurückgeben, KEIN 404 | |||
return '' | |||
end | end | ||
-- ---------- Markup → Plaintext (für Tooltip) ---------- | -- ---------- Markup → Plaintext (für Tooltip) ---------- | ||
local function stripMarkup(str) | local function stripMarkup( str ) | ||
if not str or str == '' then | if not str or str == '' then | ||
return '' | return '' | ||
end | end | ||
str = tostring(str) | str = tostring( str ) | ||
-- interne Links [[Seite|Label]] / [[Seite]] | -- interne Links [[Seite|Label]] / [[Seite]] | ||
str = str:gsub('%[%[([^%]|]+)|([^%]]+)%]%]', '%2') | str = str:gsub( '%[%[([^%]|]+)|([^%]]+)%]%]', '%2' ) | ||
str = str:gsub('%[%[([^%]]+)%]%]', '%1') | str = str:gsub( '%[%[([^%]]+)%]%]', '%1' ) | ||
-- externe Links [url Label] | -- externe Links [url Label] | ||
str = str:gsub('%[[^%s%]]+%s+([^%]]+)%]', '%1') | str = str:gsub( '%[[^%s%]]+%s+([^%]]+)%]', '%1' ) | ||
-- Hervorhebungen | -- Hervorhebungen | ||
str = str:gsub("''+", '') | str = str:gsub( "''+", '' ) | ||
-- Templates {{...}} | -- Templates {{...}} | ||
str = str:gsub('{{.-}}', '') | str = str:gsub( '{{.-}}', '' ) | ||
-- HTML-Tags | -- HTML-Tags | ||
str = str:gsub('<.->', '') | str = str:gsub( '<.->', '' ) | ||
-- Whitespace | -- Whitespace | ||
str = str:gsub('%s+', ' ') | str = str:gsub( '%s+', ' ' ) | ||
if text and text.trim then | if text and text.trim then | ||
str = text.trim(str) | str = text.trim( str ) | ||
end | end | ||
| Zeile 174: | Zeile 175: | ||
end | end | ||
local function shorten(str, max) | local function shorten( str, max ) | ||
str = stripMarkup(str) | str = stripMarkup( str ) | ||
max = tonumber(max) or 0 | max = tonumber( max ) or 0 | ||
if max <= 0 or ustr.len(str) <= max then | if max <= 0 or ustr.len( str ) <= max then | ||
return str | return str | ||
end | end | ||
local cut = ustr.sub(str, 1, max) | local cut = ustr.sub( str, 1, max ) | ||
local lastSpace = ustr.find(cut, ' [^ ]*$') | local lastSpace = ustr.find( cut, ' [^ ]*$' ) | ||
if lastSpace and lastSpace > max * 0.6 then | if lastSpace and lastSpace > max * 0.6 then | ||
cut = ustr.sub(cut, 1, lastSpace - 1) | cut = ustr.sub( cut, 1, lastSpace - 1 ) | ||
end | end | ||
| Zeile 192: | Zeile 193: | ||
-- ---------- Tooltip ---------- | -- ---------- Tooltip ---------- | ||
-- ---------- Tooltip ---------- | |||
local function buildTooltip(item, opts) | local function buildTooltip( item, opts ) | ||
opts = opts or {} | opts = opts or {} | ||
local max = opts.max or DEFAULT_TOOLTIP_MAX | local max = opts.max or DEFAULT_TOOLTIP_MAX | ||
local label = opts.label | local label = opts.label | ||
local title = getTitle(item) | local title = getTitle( item ) | ||
local desc = item.describe or item.description or '' | local desc = item.describe or item.description or '' | ||
local shortDesc = shorten(desc, max) | local shortDesc = shorten( desc, max ) | ||
local img = getImage(item) | local img = getImage( item ) | ||
local hasImg = img and img ~= '' | |||
local | local out = {} | ||
-- Wrapper | -- Wrapper | ||
table.insert( | table.insert( out, '<span class="fs-tip">' ) | ||
-- | -- sichtbares Label | ||
if label and label ~= '' then | if label and label ~= '' then | ||
table.insert( | table.insert( out, label ) | ||
else | else | ||
local target = getLinkTarget(item) | local target = getLinkTarget( item ) | ||
table.insert( | table.insert( out, '[[' .. target .. '|' .. title .. ']]' ) | ||
end | end | ||
-- Tooltip- | -- Tooltip-Content | ||
table.insert( | table.insert( out, '<span class="content">' ) | ||
-- | if hasImg then | ||
-- Layout mit Icon: Grid (.box) | |||
table.insert( out, '<span class="box">' ) | |||
table.insert( | table.insert( out, '[[Datei:' .. img .. '.png|48x48px]]' ) | ||
table.insert( out, '<span class="text">' ) | |||
else | |||
-- Kein Icon: nur Text, volle Breite | |||
table.insert( out, '<span class="text">' ) | |||
end | end | ||
-- | -- Titel | ||
table.insert( out, '<span class="title">' ) | |||
table.insert( out, title ) | |||
table.insert( out, '</span>' ) -- .title | |||
-- Beschreibung | |||
if shortDesc ~= '' then | if shortDesc ~= '' then | ||
table.insert( | table.insert( out, '<span class="desc">' ) | ||
table.insert( | table.insert( out, shortDesc ) | ||
table.insert( | table.insert( out, '</span>' ) -- .desc | ||
end | |||
-- Close .text | |||
table.insert( out, '</span>' ) | |||
-- Close .box (nur wenn Icon) | |||
if hasImg then | |||
table.insert( out, '</span>' ) -- .box | |||
end | end | ||
table.insert( | -- Close .content + .fs-tip | ||
table.insert( | table.insert( out, '</span>' ) -- .content | ||
table.insert( out, '</span>' ) -- .fs-tip | |||
return table.concat( | return table.concat( out ) | ||
end | end | ||
-- ---------- Frame-Args ---------- | -- ---------- Frame-Args ---------- | ||
local function extractKey(args) | local function extractKey( args ) | ||
if not args then | if not args then | ||
return nil | return nil | ||
| Zeile 250: | Zeile 267: | ||
end | end | ||
local function getArgKey(frame) | local function getArgKey( frame ) | ||
if not frame then | if not frame then | ||
return nil, {} | return nil, {} | ||
| Zeile 256: | Zeile 273: | ||
local args = frame.args or {} | local args = frame.args or {} | ||
local key = extractKey(args) | local key = extractKey( args ) | ||
if key and key ~= '' then | if key and key ~= '' then | ||
return key, args | return key, args | ||
| Zeile 265: | Zeile 282: | ||
if parent and parent.args then | if parent and parent.args then | ||
args = parent.args | args = parent.args | ||
key = extractKey(args) | key = extractKey( args ) | ||
if key and key ~= '' then | if key and key ~= '' then | ||
return key, args | return key, args | ||
| Zeile 273: | Zeile 290: | ||
return nil, args | return nil, args | ||
end | end | ||
-- ========================= | -- ========================= | ||
-- | -- Öffentliche Funktionen | ||
-- ========================= | -- ========================= | ||
function p.title(frame) | function p.title( frame ) | ||
local key = select(1, getArgKey(frame)) | local key = select( 1, getArgKey( frame ) ) | ||
local item = getItem(key) | local item = getItem( key ) | ||
return getTitle(item) | return getTitle( item ) | ||
end | end | ||
function p. | function p.short( frame ) | ||
local key = select(1, getArgKey(frame)) | local key = select( 1, getArgKey( frame ) ) | ||
local item = getItem(key) | local item = getItem( key ) | ||
return | return getShort( item ) | ||
end | end | ||
function p. | function p.desc( frame ) | ||
local key = select(1, getArgKey(frame)) | local key = select( 1, getArgKey( frame ) ) | ||
local item = getItem(key) | local item = getItem( key ) | ||
return item.describe or item.description or '-' | |||
end | end | ||
function p. | function p.img( frame ) | ||
local key = select(1, getArgKey(frame)) | local key = select( 1, getArgKey( frame ) ) | ||
local item = getItem(key) | local item = getItem( key ) | ||
return | -- Basename oder '' zurückgeben | ||
return getImage( item ) or '' | |||
end | end | ||
function p. | function p.link( frame ) | ||
local key = select(1, getArgKey(frame)) | local key = select( 1, getArgKey( frame ) ) | ||
local item = getItem(key) | local item = getItem( key ) | ||
return item | -- Nur das Seitentarget, z.B. "Währung#Gold" oder "Blob" | ||
return getLinkTarget( item ) | |||
end | end | ||
function p.tooltip(frame) | function p.tooltip( frame ) | ||
local key, args = getArgKey(frame) | local key, args = getArgKey( frame ) | ||
local item = getItem(key) | local item = getItem( key ) | ||
local max = tonumber(args.max or args.len or args.limit) or DEFAULT_TOOLTIP_MAX | 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 } ) | |||
local | |||
end | end | ||
return p | return p | ||
Aktuelle Version vom 1. Dezember 2025, 19:07 Uhr
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 ----------
-- ---------- 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 hasImg = img and img ~= ''
local out = {}
-- Wrapper
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
-- Tooltip-Content
table.insert( out, '<span class="content">' )
if hasImg then
-- Layout mit Icon: Grid (.box)
table.insert( out, '<span class="box">' )
table.insert( out, '[[Datei:' .. img .. '.png|48x48px]]' )
table.insert( out, '<span class="text">' )
else
-- Kein Icon: nur Text, volle Breite
table.insert( out, '<span class="text">' )
end
-- Titel
table.insert( out, '<span class="title">' )
table.insert( out, title )
table.insert( out, '</span>' ) -- .title
-- Beschreibung
if shortDesc ~= '' then
table.insert( out, '<span class="desc">' )
table.insert( out, shortDesc )
table.insert( out, '</span>' ) -- .desc
end
-- Close .text
table.insert( out, '</span>' )
-- Close .box (nur wenn Icon)
if hasImg then
table.insert( out, '</span>' ) -- .box
end
-- Close .content + .fs-tip
table.insert( out, '</span>' ) -- .content
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