Star Citizen Wiki
Wir laden dich herzlich auf unseren Star Citizen Wiki Discord Server ein! Dein direkter Draht für Fragen, Anmerkungen oder Kritik.

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)

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'

--- 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
            t.capiunto:addRow( label, row.data, row.class, row.rowClass )
        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

            t.capiunto:addRow( nil, label, row.class, row.rowClass )
        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

--- 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 )
    type = type or 'row'

	if t.removeEmpty == true then
		if type == 'row' and ( rowData == nil or rowData == t.emptyString ) then
			return t
		end
	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 )
    local rowClass = rowClass or ''
    rowClass = rowClass .. ' 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 )
    local rowClass = rowClass or ''
    rowClass = rowClass .. ' 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 )
    return t:addRow( text, nil, class, 'row-subheader', style, 'subheader' )
end

--- Adds a caption to the infobox
function methodtable.addCaption( t, text, class, style )
    return addSpecialRow( t, 'title', text, class, style )
end

--- Adds a caption to the infobox
function methodtable.addTop( t, text, class, style )
    return addSpecialRow( t, 'top', text, class, style )
end

--- Adds a bottom to the infobox
function methodtable.addBottom( t, text, class, style )
    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 )
    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

    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

    local imageOptions = buildOptions( options )
    if imageOptions ~= '' then
        imageOptions = '|' .. imageOptions
    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 )
    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.allowReplace = flag
end

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

    return t.capiunto
end

--- Returns the table string
--- @return string
function methodtable.getBoxText( t )
    return tostring( t:getBox() )
end

--- Init the infobox
--- @param options table|nil Option table passed to capiunto.create
function infobox.create( options )
    local instance = {
        -- 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,
    }

    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

    setmetatable( instance, metatable )

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

    return instance
end

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

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

    local box = infobox.create( options )

    if arguments.image ~= nil then
        box:addImage( arguments.image,{
            'frameless',
            '600px'
        } )

        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.