Star Citizen Wiki Modul:Infobox
Wir laden dich herzlich auf den Star Citizen Wiki Discord Server ein! Du kannst uns auch auf unserem neuen YouTube-Chanel finden!

Modul:Infobox

Aus Star Citizen Wiki

Vorlage zur Erzeugung von Infoboxen.

Jedes Vorlagenargument wird als Zeile in der Tabelle angezeigt.

HINWEIS Lua-Tabellen behalten die Reihenfolge nicht bei, um dennoch die Reihen in der richtigen Reihenfolge anzeigen zu können sortiert diese Vorlage die angegebenen Argumente ALPHABETISCH!

Du kannst den Argumenten Zahlen voranstellen, um die Reihenfolge feszulegen: Beispiel Template:

{{Infobox
|1-header=Kopfzeile für Block eins
|1.1-RowLabel=Dies ist der Inhalt für Zeile 1.1
|1.2-RowLabel=Dies ist wiederum der Inhalt
|2-subheader=Teilüberschrift
|2.1-Label=Inhalt
|2.2...
}}

Optionen

Reihen und Kopfzeilen können Klassen und Zeilenklassen hinzugefügt werden:

{{Infobox
|Reihe=Inhalt<>Klasse<>Reihenklasse
}}

Kopiervorlage

{{Infobox
|image=Kelos_Costigan.png
|title=Kelos Costigan
|bodyClass=floatright
|0-title=Kelos Costigan
|1-header=Informationen
|1.1-Geschlecht=Männlich<><>col2
|1.2-Zugehörigkeit=Menschen<><>col2
|1.3-Geboren=2664<><>col2
|1.4-Gestorben=-<><>col2
|2-header=Weitere Infos
|2.1-Beruf=United Empire of Earth Imperator (2941-2950)
}}

Beispiel

Die oben genannte Kopiervorlage erzeugt die folgende Infobox:

Kelos Costigan
Kelos Costigan.png
Kelos Costigan
Informationen
Geschlecht Männlich
Zugehörigkeit Menschen
Geboren 2664
Gestorben -
Weitere Infos
Beruf United Empire of Earth Imperator (2941-2950)


Vorlage zur Erzeugung von Infoboxen. Jeder angegebene Parameter wird als neue Zeile behandelt.

Vorlagenparameter

Diese Vorlage bevorzugt Blockformatierung von Parametern.

ParameterBeschreibungTypStatus
Bildimage

Bild der Infobox

Beispiel
Kelos_Costigan.png
Dateivorgeschlagen
Titeltitle

Text, der in der Beschriftung oberhalb der Tabelle erscheinen soll

Zeichenfolgevorgeschlagen
Top Titeltop

Text, der in der obersten Zelle der Tabelle stehen soll

Zeichenfolgevorgeschlagen
Fußnotebottom

Text, der in der untersten Zelle platziert werden soll; dies könnte für Fußnoten, Siehe-auch und andere derartige Informationen verwendet werden

Zeichenfolgevorgeschlagen

local Infobox = {}
local metatable = {}
local methodtable = {}

metatable.__index = methodtable

metatable.__tostring = function( t )
    return tostring( t:getBoxText() )
end

-- Uses capiunto as the base
local capiunto = require 'capiunto'
local libraryUtil = require( 'libraryUtil' )

--- Returns true if input is a string or number
--- @param input string|number|table
--- @return boolean
local function verifyStringNum( input )
    return type( input ) == 'string' or type( input ) == 'number'
end

--- This fills the box with content
local function addBoxContent( t )
    if t.contentAdded then
        return
    end

    for _, row in ipairs( t.rows ) do
        local label = tostring( row.label )

        if row.type == 'row' then
            if (type( label ) == 'string' or type( label ) == 'number') and ( type( row.data ) == 'string' or type( row.data ) == 'number' ) then
                t.capiunto:addRow( label, row.data, row.class, row.rowClass )
            end
        elseif row.type == 'header' or row.type == 'image' then
            if row.type == 'image' and row.rowClass ~= 'row-image' then
                row.rowClass = row.rowClass .. ' row-image'
            end

            -- Only add the header if it has content
            if mw.ustring.find( row.rowClass, 'row-header', 1, true ) ~= nil and t.headerContentCounts[ label ] ~= nil and t.headerContentCounts[ label ] == 0 then
                -- skip add
            else
                t.capiunto:addRow( nil, label, row.class, row.rowClass )
            end
        elseif row.type == 'subheader' then
            t.capiunto:addSubHeader( label, row.class, row.style )
        end
    end

    t.contentAdded = true
end

--- Iterate table in key order
local function spairs( t, orderFn )
    -- collect the keys
    local keys = {}
    for k, v in pairs( t ) do
        if v ~= nil then
            keys[ #keys + 1 ] = tostring( k )
        end
    end

    -- if order function given, sort by it by passing the table and keys a, b,
    -- otherwise just sort the keys
    if orderFn then
        table.sort( keys, function( a, b ) return orderFn( t, a, b ) end )
    else
        table.sort( keys )
    end

    -- return the iterator function
    local i = 0
    return function()
        i = i + 1
        if keys[ i ] then
            return keys[ i ], t[ keys[ i ] ]
        end
    end
end

--- Parse all available capiunto options from a table
--- Returns only non nil values
---
--- @param args table
--- @return table
local function parseArgs( args )
    local options = {
        [ 'isChild' ]      = args[ 'isChild' ]      or nil,
        [ 'isSubbox' ]     = args[ 'isSubbox' ]     or nil,

        [ 'title' ]        = args[ 'title' ]        or nil,
        [ 'titleClass' ]   = args[ 'titleClass' ]   or nil,
        [ 'titleStyle' ]   = args[ 'titleStyle' ]   or nil,

        [ 'top' ]          = args[ 'top' ]          or nil,
        [ 'topClass' ]     = args[ 'topClass' ]     or nil,
        [ 'topStyle' ]     = args[ 'topStyle' ]     or nil,

        [ 'captionStyle' ] = args[ 'captionStyle' ] or nil,
        [ 'imageStyle' ]   = args[ 'imageStyle' ]   or nil,
        [ 'imageClass' ]   = args[ 'imageClass' ]   or nil,

        [ 'bodyClass' ]    = args[ 'bodyClass' ]    or nil,
        [ 'bodyStyle' ]    = args[ 'bodyStyle' ]    or nil,
        [ 'headerStyle' ]  = args[ 'headerStyle' ]  or nil,
        [ 'labelStyle' ]   = args[ 'labelStyle' ]   or nil,
        [ 'dataStyle' ]    = args[ 'dataStyle' ]    or nil,
    }

    local i = 0
    local keys, values = {}, {}
    for k, v in pairs( options ) do
        i = i + 1
        keys[ i ] = k
        values[ i ] = v
    end

    while i > 0 do
        if keys[ i ] == nil then
            table.remove( keys, i )
            table.remove( values, i )
            break
        end
        i = i - 1
    end

    local finalOptions = {}
    for i = 1, #keys do
        finalOptions[ keys[ i ] ] = values[ i ]
    end

    local finalArgs = {}
    for k, v in pairs( args ) do
        if finalOptions[ k ] == nil and v ~= nil then
            finalArgs[ k ] = v
        end
    end

    return finalOptions, finalArgs
end

--- Replaces a row if labels match and returns the replaced index
--- Otherwise returns the next free index
---
--- @return number New index
local function replaceInRows( t, targetLabel )
    for idx, row in ipairs( t.rows ) do
        if row.label == targetLabel then
            table.remove( t.rows, idx )
            return idx
        end
    end

    return #t.rows + 1
end

--- Adds one of three special rows to the infobox
--- As defined by Capiunto
--- Available rowTypes are: title (caption), top (first row), bottom (last row)
---
--- @param t table The infobox
--- @param rowType string title, top or bottom
--- @param class string Row class
--- @param style string Css style
--- @return table
local function addSpecialRow( t, rowType, text, class, style )
    if t.capiunto == nil then
        return
    end

    if verifyStringNum( text ) then
        t.capiunto.args[ rowType ] = text
    end

    if type( class ) == 'string' then
        t.capiunto.args[ rowType .. 'Class' ] = class
    end

    if type( style ) == 'string' then
        t.capiunto.args[ rowType .. 'Style' ] = style
    end

    return t
end

--- Generates a link to Special:Upload with pre-defined parameters
---
--- @param fileName string|nil The filename including the extension
--- @param title string The title of the infobox
local function generateUploadLink( fileName, category )
	local title = mw.title.new( 'Special:Upload' )

	if fileName == nil then
		fileName = mw.title.getCurrentTitle().text .. '.jpg'
	end
	
	if category == nil then
		category = mw.title.getCurrentTitle().text
	end

	local description = [==[
=={{int:filedesc}}==
{{Information
|description={{de|1=%s}}
|date=%s
|source=<!-- BITTE LINK ZU BILD EINFÜGEN -->
|author=RSI
|permission=
|other versions=
}}

=={{int:license-header}}==
{{license-rsi}}

[[Kategorie:%s]]
	]==]

	description = mw.ustring.format(
		description,
		category,
		mw.getContentLanguage():formatDate('Y-m-d H:i:s'),
		category
	)

	local parameters = {
		[ 'wpDestFile' ] = fileName,
		[ 'wpLicense' ] = 'license-rsi',
		[ 'wpUploadDescription' ] = description
	}

	return title:fullUrl( parameters, 'https' )
end

--- Generates a link to Special:Uploadwizard with pre-defined parameters
---
--- @param fileName string|nil The filename excluding the extension
--- @param title string The title of the infobox
local function generateUploadwizardLink( fileName, category )
	local title = mw.title.new( 'Special:Uploadwizard' )

	if fileName == nil then
		fileName = mw.title.getCurrentTitle().text
	end

	if category == nil then
		category = mw.title.getCurrentTitle().text
	end

	local parameters = {
		[ 'categories' ] = category,
		[ 'title' ] = fileName,
		[ 'description' ] = fileName,
		-- Missing: Date
		-- Missing pre license select
	}

	return title:fullUrl( parameters, 'https' )
end

--- Base method to add a row
--- @see https://www.mediawiki.org/wiki/Extension:Capiunto/Infobox
--- @param t table The instance
--- @param rowLabel string Row label
--- @param rowData string Row content (can be anything)
--- @param dataClass string CSS class added to data
--- @param rowCssClass string CSS class added to row
--- @param rowStyle string CSS style only used if type is 'subheader'!
--- @param type string Either 'row', 'header', 'image' or 'subheader'
function methodtable.addRow( t, rowLabel, rowData, dataClass, rowCssClass, rowStyle, type )
    t.checkSelf( t, 'addRow' )

    type = type or 'row'

    if t.removeEmpty == true then
        if type == 'row' and ( rowData == nil or rowData == t.emptyString ) then
            return t
        end
    end

    if type == 'header' then
        t.currentHeader = rowLabel

        if t.headerContentCounts[ rowLabel ] == nil then
            local count = 0
            -- A "single" header is a header without content
            -- This is used to circumvent removing the header as it as no content
            if dataClass == 'single' then
                count = 1
            end

            t.headerContentCounts[ rowLabel ] = count
        end
    end

    -- increment the header count
    if t.currentHeader ~= nil and type == 'row' and t.headerContentCounts[ t.currentHeader ] ~= nil then
        t.headerContentCounts[ t.currentHeader ] = t.headerContentCounts[ t.currentHeader ] + 1
    end

    local pos = -1
    if t.allowReplace == true and #t.rows > 0 then
        pos = replaceInRows( t, rowLabel )
    else
        t.rowCount = t.rowCount + 1
        pos = t.rowCount
    end

    if rowCssClass == nil then
        rowCssClass = 'row-' .. type
        if rowCssClass == 'row-row' then
            rowCssClass = 'row'
        end
    end

    if not mw.ustring.match( rowCssClass, 'row' ) then
        local toAdd = type
        if toAdd ~= 'row' then
            toAdd = 'row-' .. type
        end

        rowCssClass = rowCssClass .. ' ' .. toAdd
    end

    table.insert( t.rows, pos, {
        type = type,
        label = rowLabel,
        data = rowData or nil,
        class = dataClass or nil,
        rowClass = rowCssClass,
        style = rowStyle or nil
    })

    return t
end

--- Adds a header to the infobox
function methodtable.addHeader( t, text, class, rowClass )
    t.checkSelf( t, 'addHeader' )

    rowClass = ( rowClass or '' ) .. ' row-header'

    return t:addRow( text, nil, class, rowClass, nil, 'header' )
end

--- Adds a title row to the infobox
function methodtable.addTitle( t, text, class, rowClass )
    t.checkSelf( t, 'addTitle' )

    rowClass = ( rowClass or '' ) .. ' row-title'

    return t:addRow( text, nil, class, rowClass, nil, 'header' )
end

--- Adds a subheader to the infobox
function methodtable.addSubHeader( t, text, class, style )
    t.checkSelf( t, 'addSubHeader' )

    return t:addRow( text, nil, class, 'row-subheader', style, 'subheader' )
end

--- Adds a caption to the infobox
function methodtable.addCaption( t, text, class, style )
    t.checkSelf( t, 'addCaption' )

    return addSpecialRow( t, 'title', text, class, style )
end

--- Adds a caption to the infobox
function methodtable.addTop( t, text, class, style )
    t.checkSelf( t, 'addTop' )

    return addSpecialRow( t, 'top', text, class, style )
end

--- Adds a bottom to the infobox
function methodtable.addBottom( t, text, class, style )
    t.checkSelf( t, 'addBottom' )

    return addSpecialRow( t, 'bottom', text, class, style )
end

--- Adds an image to the infobox
--- @param file string Wiki page filename
--- @param options table Image options
--- @param checkExistence boolean True to check if the file exists
function methodtable.addImage( t, file, options, checkExistence )
    t.checkSelf( t, 'addImage' )
    local isPlaceholder = false

    if type( file ) ~= 'string' then
        if t.displayPlaceholder == false then
            return
        end

        file = t.placeholderImage
        isPlaceholder = true
    end

    local exists = true
    local title = mw.title.new( mw.uri.decode( file, 'WIKI' ), 6 )

    if title == nil then
        return
    end

    if type( options ) == 'string' then
        options = {
            [ 'rowClass' ] = options
        }
    else
        options = options or {}
    end

    if checkExistence ~= nil and checkExistence == true then
        exists = title.exists
    end

    local class = options[ 'rowClass' ] or nil

    local function buildOptions( imageOptions )
        local out = {}

        for k, v in pairs( imageOptions ) do
            if k ~= 'rowClass' and type( k ) == 'string' and type( v ) == 'string' then
                table.insert( out, k .. '=' .. v )
            elseif type( k ) == 'number' then
                table.insert( out, v )
            end
        end

        return table.concat( out, '|' )
    end

    if isPlaceholder == true then
    	options[ 'link' ] = generateUploadLink()
    	if class == nil then
    		class = 'placeholder'
		else
			class = class .. ' placeholder'
		end
	end

    local imageOptions = buildOptions( options )
    if imageOptions ~= '' then
        imageOptions = '|' .. imageOptions
        
        if isPlaceholder == true then
        	imageOptions = imageOptions .. '|Klicke um Bild hochzuladen'
    	end
    end

    local header = '[[' .. title.prefixedText .. imageOptions .. ']]'

    if exists == false then
        header = 'Datei fehlt'
    end

    return t:addRow( header, nil, class, 'row-image', nil, 'image' )
end

--- Allows to add arbitrary rows from template args
--- @param args table Template arguments
--- @param prefix string|nil An optional prefix that each argument must have to be added as a row
--- @param allowedKeys table|nil An optional table of keys that are allowed as rows, are passed to ustring.match
---
--- Example param = !row -> Only Template arguments in the form of |!row...=Content are added as Rows
--- The prefix gets replaced from each key: |!rowLabel=Content  => Label=Content
---
--- The row type can be set by adding 'subheader' or 'header' to the key
--- Example: |header1=Content => Header row with content 'content' added
--- Multiple headers must be suffixed by numbers
---
--- !!! NOTE !!!
--- Lua tables do not preserve order, to mitigate this, this module SORTS the given arguments ALPHABETICALLY
--- You can prefix arguments with numbers to preserve the order
--- Example Template:
--- {{Infobox
--- |1-header=Header for block one
--- |1.1-RowLabel=This is the content for row 1.1
--- |1.2-RowLabel=This again is the content
--- |2-subheader=Subheader
--- |2.1-Label=Content
--- |2.2...
--- }}
---
--- Example Module Call:
--- infobox.addRowsFromArgs({
---   [ '1-header' ] = 'Header for block one',
---   [ '1.1-RowLabel' ] = 'This is...',
--- })
function methodtable.addRowsFromArgs( t, args, prefix, allowedKeys )
    t.checkSelf( t, 'addRowsFromArgs' )

    if type( args ) ~= 'table' then
        return
    end

    _, args = parseArgs( args )

    local function canAdd( key )
        if key == 'image' then -- Image is added separately
            return false
        end

        if prefix == nil then
            if type( allowedKeys ) == 'table' then
                for _, allowed in pairs( allowedKeys ) do
                    if mw.ustring.match( key, allowed ) then
                        return true
                    end
                end

                return false
            end

            return true
        elseif type( prefix ) == 'string' then
            return mw.ustring.match( key, prefix )
        end

        return true
    end

    for k, v in spairs( args ) do
        if type( k ) == 'string' and type( v ) == 'string' then
            if canAdd( k ) then
                if prefix~= nil and type( prefix ) == 'string' then
                    k = mw.ustring.gsub( k, prefix, '' )
                end

                -- Remove Digits - and . at start of label
                k = mw.ustring.gsub( k, '^[%d%-%.]+', '' )
                -- Removes digits at the end, should enable MW Infobox behaviour
                k = mw.ustring.gsub( k, '[%d]+$', '' )

                local splitted = mw.text.split( v, '<>', true )

                local label = splitted[1]
                local class = splitted[2] or ''
                local rowClass = splitted[3] or ''

                if mw.ustring.match( k, 'subheader' ) then
                    t:addSubHeader( v )
                elseif mw.ustring.match( k, 'header' ) then
                    t:addHeader( label, class, rowClass )
                elseif mw.ustring.match( k, 'title' ) then
                    t:addTitle( label, class, rowClass )
                elseif mw.ustring.match( k, 'caption' ) then
                    t:addCaption( label, class, rowClass )
                elseif mw.ustring.match( k, 'top' ) then
                    t:addTop( label, class, rowClass )
                elseif mw.ustring.match( k, 'bottom' ) then
                    t:addBottom( label, class, rowClass )
                else
                    t:addRow( k, label, class, rowClass )
                end
            end
        end
    end

    return t
end

--- Flag to allow or disable row replacing
--- @param flag boolean
function methodtable.setAllowReplace( t, flag )
    t.checkSelf( t, 'setAllowReplace' )

    t.allowReplace = flag
end

--- Returns the raw capiunto box
--- @return table
function methodtable.getBox( t )
    t.checkSelf( t, 'getBox' )

    addBoxContent( t )

    return t.capiunto
end

--- Returns the table string
--- @return string
function methodtable.getBoxText( t )
    t.checkSelf( t, 'getBoxText' )

    return tostring( t:getBox() )
end

--- Init the infobox
--- @param options table|nil Option table passed to capiunto.create
function Infobox.create( options )
    local instance = {
        -- Table containing Header = count of rows
        headerContentCounts = {},
        -- The currently active header
        currentHeader = nil,
        -- The row tables
        rows = {},
        -- Total number of rows in the box
        rowCount = 0,
        -- Capiunto table
        capiunto = {},
        -- Flag to stop adding rows to the box
        contentAdded = false,
        -- Flag to enable replacing already added rows
        allowReplace = false,
        -- Flag to discard empty rows
        removeEmpty = false,
        -- Optional string which is valued as empty
        emptyString = nil,
        -- Display a placeholder image if addImage does not find an image
        displayPlaceholder = true,
        -- Placeholder Image
        placeholderImage = 'Platzhalter.webp',
    }

    if options.allowReplace ~= nil then
        instance.allowReplace = options.allowReplace
        options.allowReplace = nil
    end

    if options.removeEmpty ~= nil then
        instance.removeEmpty = true
        options.removeEmpty = nil
    end

    if options.emptyString ~= nil then
        instance.emptyString = options.emptyString
        options.emptyString = nil
    end

    if options.displayPlaceholder ~= nil then
        instance.displayPlaceholder = options.displayPlaceholder
        options.displayPlaceholder = nil
    end

    if options.placeholderImage ~= nil then
        instance.placeholderImage = options.placeholderImage
        options.placeholderImage = nil
    end

    setmetatable( instance, metatable )

    instance.capiunto = capiunto.create( parseArgs( options or {} ) )

    instance.checkSelf = libraryUtil.makeCheckSelfFunction( 'Infobox', 'instance', instance, 'Method Call' )

    return instance
end

--- Create a infobox from args
--- @param frame table
--- @return string
function Infobox.fromArgs( frame )
    local arguments = require( 'Module:Arguments' ).getArgs( frame )
    local options, args = parseArgs( arguments )

    if options.bodyClass == nil then
        options.bodyClass = 'floatright'
    end

    local box = Infobox.create( options )

    box:addImage( arguments.image,{
        'frameless',
        '600px'
    } )

    if arguments.image ~= nil then
        arguments.image = nil
    end

    box:addRowsFromArgs( args )

    return tostring( box )
end

return Infobox
Cookies helfen uns bei der Bereitstellung dieses Wikis. Durch die Nutzung des Star Citizen Wiki erklärst du dich damit einverstanden, dass wir Cookies speichern.