Modul:Vorlage:Literatur

aus Wikipedia, der freien Enzyklopädie
local Serial = "2019-06-11"
--[=[
Unterstützung für {{Literatur}}
]=]


-- Global
local Zitation
local Selbst = "Vorlage:Literatur"
local KategorieBeginn  =  "Wikipedia:Vorlagenfehler"
local Kategorien       =
                 { Intern              = { s = "/Interner Fehler" },
                   Parameter           = { s = "/Parameterfehler" },
                   MonatTag            = { s = "/Parameter Monat, Tag" },
                   Temp1               = { s = "/Temp1" },
                   Temp2               = { s = "/Temp2" },
                   Temp3               = { s = "/Temp3" },
                   Temp4               = { s = "/Temp4" },
                 }
local Fehler = false
local Schrei
local Export = { }



local function fehler( art, anzeige )
    -- Ein Fehler ist aufgetreten
    -- Parameter:
    --     art      -- string mit Schlüsselwort zum Typ
    --     anzeige  -- string mit Einzelheiten, oder nil
    local t
    if not Fehler then
        Fehler = { Intern    = { s = "Interner Fehler",
                                 k = "Intern" },
                   Modul     = { s = "Modul-Seite fehlt",
                                 k = "Intern" },
                   Format    = { s = "Parameterformat" },
                   Konflikt  = { s = "Parameterkonflikt",
                                 k = "Parameter" },
                   Parameter = { s = "Parameterfehler",
                                 k = "Parameter" },
                   Wert      = { s = "Werte ungültig",
                                 k = "Parameter" },
                   MonatTag  = { k = "MonatTag" },
                   Temp1     = { k = "Temp1" },
                   Temp2     = { k = "Temp2" },
                   Temp3     = { k = "Temp3" },
                   Temp4     = { k = "Temp4" }
                 }
    end
    t = Fehler[ art ]
    if t then
        if t.s  and  not t.e then
            t.e = ""
        end
        if anzeige then
            local s = mw.text.nowiki( anzeige )
            if t.e then
                t.e = string.format( "%s; %s", t.e, s )
            else
                t.e = s
            end
        end
        if t.k then
            local wk = Kategorien[ t.k ]
            if wk then
                wk.e = true
            else
                Fehler.Intern.e     = "Wartungskat " .. wk
                Kategorien.Intern.e = true
            end
        end
    else
        Fehler.Intern.e     = string.format( "fehler(%s) %s",
                                             art, anzeige or "???" )
        Kategorien.Intern.e = true
    end
end -- fehler()



local function fehlerliste()
    -- Auflistung aller Fehlermeldungen und Kategorien
    -- Rückgabewert: string mit formatiertem Ergebnis
    local r = ""
    local s
    if Fehler then
        local sep = ""
        local suffix
        for k, v in pairs( Fehler ) do
             if v.e then
                if v.e:sub( 1, 1 ) == ";" then
                    suffix = v.s .. v.e
                elseif v.s then
                    suffix = string.format( "%s: %s", v.s, v.e )
                else
                    suffix = v.e
                end
                Schrei = string.format( "%s%s*** %s",
                                        Schrei or "",
                                        sep,
                                        suffix )
                sep    = " "
            end
        end -- for k, v
    end
    for k, v in pairs( Kategorien ) do
        if v.e then
            if v.s:sub( 1, 1 ) == "/" then
                s = Selbst
            else
                s = ""
            end
            r = string.format( "%s[[Kategorie:%s/%s%s]]",
                               r, KategorieBeginn, s, v.s )
        end
    end -- for k, v
    return r
end -- fehlerliste()



local folder = function ()
    -- Parameter-Konfiguration laden
    local s = string.format( "Module:%s/params", Selbst )
    local lucky, params = pcall( mw.loadData, s )
    if type( params ) == "table" then
        Export.params = Export.flat( params )
    else
        error( string.format( "[[%s]] fehlt", s ) )
    end
end -- folder()



-------------------------------------------------------------------------



Export.flat = function ( adapt )
    -- Deep copy
    -- Parameter:
    --     adapt  -- something
    -- Returns atomic value, or deep copy of a table with no metatable
    local r
    if type( adapt ) == "table" then
        r = { }
        for k, v in pairs( adapt ) do
            r[ k ] = Export.flat( v )
        end -- for k, v
    else
        r = adapt
    end
    return r
end -- Export.flat()



Export.Datum = function ( args )
    local r = args.Jahr
    local shit
    if r then
        if r:match( "^%d+$" ) then
            local DateTime = Zitation.fetch( "DateTime" )
            local o = DateTime( r )
            if args.Woche and o then
                o.week = tonumber( args.Woche )
                if tostring( o.week ) ~= args.Woche then
                    fehler( "Wert", "'Woche'=" .. args.Woche )
                    r = false
                end
            elseif args.Monat then
                local s
                if args.Monat:match( "%l" ) then
                    local dm = DateTime( args.Monat )
                    if dm and o and dm.month then
                        o.month = dm.month
                    else
                        shit = "'Monat'=" .. args.Monat
                        if args.Nummer then
                            args.Nummer = string.format( "%s, %s",
                                                         args.Nummer,
                                                         args.Monat )
                        else
                            args.Nummer = args.Monat
                        end
                        if not args.Datum then
                            args.Datum = r
                        end
                        r = false
                    end
                else
                    s = args.Monat:match( "^0?(1?%d)%.?$" )
                    if s and o then
                        o.month = tonumber( s )
                    end
                    if o and tostring( o.month ) ~= s then
                        fehler( "MonatTag",  "'Monat'=" .. args.Monat )
                        r = false
                    elseif s ~= args.Monat  and
                           "0" .. s ~= args.Monat then
                        fehler( "MonatTag",  "'Monat'=" .. args.Monat )
                    end
                end
                if o and o.month  and  args.Tag then
                    s = args.Tag:match( "^0?([123]?%d)%.?$" )
                    if s then
                        o.dom = tonumber( s )
                    end
                    if tostring( o.dom ) ~= s then
                        shit = "'Tag'=" .. args.Tag
                        r = false
                    elseif s ~= args.Tag  and
                           "0" .. s ~= args.Tag  and
                           s .. "." ~= args.Tag then
                        fehler( "MonatTag",  "'Tag'=" .. args.Tag )
                    end
                end
            elseif args.Tag then
                shit = "'Tag' ohne 'Monat'"
                r = false
            end
            if r and o then
                r = o
                args.Datum = o
            end
        elseif r:match( "^%[%d%d%d%d%]$" ) then
            args.Datum = r:match( "^%[(%d+)%]$" )
            if args.Kommentar then
                args.Kommentar = ", " .. args.Kommentar
            else
                args.Kommentar = ""
            end
            args.Kommentar  = string.format( "o. J. %s%s",
                                             args.Jahr, args.Kommentar )
            fehler( "Wert", "'Datum'=o.J." )
        else
            if args.Datum then
                fehler( "Wert",  "'Jahr'=" .. args.Jahr )
            else
                args.Datum = args.Jahr
            end
        end
    elseif args.Monat or args.Woche or args.Tag then
        fehler( "Konflikt", "'Jahr' fehlt bei spezifischem Datum" )
    else
        r = args.Datum
    end
    if shit then
       fehler( "MonatTag", shit )
    end
    return r
end -- Export.Datum()



local Band = function ( args )
    --    OBSOLET   nach Bereinigung in allen NR
    if args.Band  and  not args.Sammelwerk then
        if args.Reihe  and  not args.BandReihe then
            args.BandReihe = args.Band
            args.Band      = nil
            fehler( "Temp4" )
            fehler( "Parameter", "Band= meint BandReihe=" )
        elseif args.Titel  and
               args.Titel:find( " In: " ) then
            fehler( "Parameter", "Band= ohne Sammelwerk=" )
        end
    end
end -- Band()



local Nummer = function ( args )
    --    OBSOLET   nach Bereinigung in allen NR
    if args.Nummer  and  not args.Sammelwerk then
        if args.Reihe  and  not args.NummerReihe then
            args.NummerReihe = args.Nummer
            args.Nummer      = nil
            fehler( "Temp4" )
            fehler( "Parameter", "Nummer= meint NummerReihe=" )
        elseif args.Titel  and
               args.Titel:find( " In: " ) then
            fehler( "Parameter", "Nummer= ohne Sammelwerk=" )
        end
    end
end -- Nummer()



local Herausgeber = function ( args )
    --    OBSOLET   nach Übernahme in Zentralmodul
    if args.Autor  and  args.Autor:find( "(Hrsg.)", 1, true ) then
        fehler( "Wert",
                "Autor= mit Klammer (Hrsg.); dafür Hrsg= verwenden" )
    end
end -- Herausgeber()



local Sprache = function ( args )
    --    OBSOLET   nach Bereinigung im Benutzerbereich
    if args.Originalsprache  and
       not args.Originaltitel  and
       not args["Übersetzer"]  and
       not args.Sprache then
        local t = mw.title.getCurrentTitle()
        if t.namespace == 2  or  t.namespace == 3 then
            args.Sprache         = args.Originalsprache
            args.Originalsprache = nil
            fehler( "Parameter",
                    "Sprache= nutzen statt Originalsprache="
                                                        .. args.Sprache )
            fehler( "Temp1" )
        end
    end
end -- Sprache()



local format = function ( args )
    -- Analysiere Argumente und bilde formatierte Zitation
    -- Parameter:
    --     args    -- table mit Vorlagenparametern
    -- Rückgabewert: string mit formatierter Zitation
    local pars = Zitation.filter( args, Export.params.valid )
    local r, schrott
    Export.Datum( pars )
    Herausgeber( pars )
    Band( pars )
    Nummer( pars )
    Sprache( pars )
    Zitation.filler( pars, Export.params.map )
    if Zitation.o then
        Zitation.fill( "leise",  "leiser",   true )
        Zitation.fill( "leise",  "Vorlage",  pars.Vorlage or Selbst )
        Zitation.o.coins = true
    end
    r, schrott = Zitation.format()
    if schrott then
        if Schrei then
            Schrei = string.format( "%s *** %s", Schrei, schrott )
        else
            Schrei = schrott
        end
    end
    return r
end -- format()



local function f( arglist, frame )
    -- Hauptfunktion zur Steuerung des Gesamtablaufs
    -- Parameter:
    --     arglist  -- table, mit Vorlagenparametern
    --     frame    -- object, oder nil
    -- Rückgabewert: string mit formatiertem Gesamtergebnis
    --                      einschließlich Fehlerliste und Kategorien
    local lucky, r = pcall( require, "Modul:Zitation" )
    if type( r ) == "table" then
        Zitation       = r.Zitation()
        Zitation.frame = frame
        folder()
        r = string.format( "%s%s%s",
                           format( arglist ),
                           fehlerliste(),
                           Zitation.failure( Schrei ) )
    else
        fehler( "Modul", r )
        r = fehlerliste()
    end
    return r
end -- f()



-- Export
local p = {}

function p.export()
    folder()
    return Export
end

function p.test( a )
    local lucky, r = pcall( f, a )
    return r
end

function p.f( frame )
    local lucky, r = pcall( f, frame:getParent().args, frame )
    if not lucky then
        mw.log( r )
        fehler( "Intern", r )
        r = fehlerliste()
    end
    return r
end

function p.failsafe()
    return Serial
end

return p