Modul:Vorlage:Kurier-Ticker

aus Wikipedia, der freien Enzyklopädie
local Serial = "2021-06-30"
--[=[
Zeilendarstellung und Syntaxcheck für Vorlage:Kurier-Ticker
]=]



local MaxChars      = 200
local MaxWidthCell  = 150
local MaxWidthTable = 186
local BabelPar      = { ["color 1"]     = "#000000",
                        ["color 2"]     = "#FFFFFF",
                        ["color 3"]     = "#B22222",
                        ["letter size"] = "0.9em"
                      }
local StyleTable    = string.format( "%s; %s; %s; %s;",
                                     "font-family:sans-serif",
                                     "line-height:1.1em",
                                     "margin-left:-2px",
                                     "overflow:hidden" )
local StyleText     = string.format( "%s; %s;",
                                     "overflow:hidden",
                                     "white-space:nowrap" )
local Summary       = "[[WP:K #NeueÜberschrift|NeueÜberschrift]] von [[Benutzer:]]"
local Ticker        = mw.title.makeTitle( 10, "Kurier-Ticker" )
local Current, Extern, Frame, Leader, Leading, Learn, Paper



local function faculty( ask )
    local r
    if ask then
        r = not ask:match( "^[0nN%-]" )
    end
    return r
end -- faculty()



local function fault( alert )
    return tostring( mw.html.create( "span" )
                            :addClass( "error" )
                            :css( "background-color", "#FFFF00" )
                            :wikitext( alert ) )
end -- fault()



local function feeding()
    -- Definition wird bearbeitet
    if type( Learn ) ~= "boolean" then
        Learn = ( Frame:preprocess( "{{REVISIONID}}" ) == "" )
    end
    return Learn
end -- feeding()



local function fetch( access )
    -- Modulbibliothek anfordern
    --     access   -- string, ID
    -- Rückgabe: table, Modulbibliothek
    -- Exception: Modulbibliothek nicht erreichbar
    local r
    Extern = Extern or { }
    r = Extern[ access ]
    if type( r ) ~= "table" then
        local lucky, g = pcall( require,  "Module:" .. access )
        if type( g ) == "table" then
            if type( g[ access ] ) == "function" then
                r                = g[ access ]()
                Extern[ access ] = r
            else
                error( "Bad init " .. access )
            end
        else
            error( r )
        end
    end
    return r
end -- fetch()



local function first()
    -- Vorlagenseite selbst
    if type( Leading ) ~= "boolean" then
        Current = Current or mw.title.getCurrentTitle()
        Leading = mw.title.equals( Current, Ticker )
    end
    return Leading
end -- first()



local function flat( apply )
    -- Wikitext in Flachtext wandeln
    --     apply   -- string, Wikitext
    -- Rückgabe: string, plain text
    local r = apply
    if r:find( "[", 1, true ) then
        r = fetch( "WLink" ).getPlain( r )
    end
    if r:find( "<", 1, true )  or
       r:find( "''", 1, true ) then
        r = fetch( "Text" ).getPlain( r )
    end
    if r:find( "  ", 1, true ) then
        r = r:gsub( "  +", " " )
    end
    return mw.text.trim( r )
end -- flat()



local function folder()
    -- Kurierseite
    -- Rückgabe: mw.title, Kurierseite
    if not Paper then
        Paper = mw.title.makeTitle( 4, "Kurier" )
    end
    return Paper
end -- folder()



local function headlines( at, attach )
    -- Überschriften-check und Tooltips
    --     at       -- table[ 3 ], Überschriften
    --     attach   -- number, 1, 3: Tooltips generieren
    -- Rückgabe: string/false, Wikitext oder table
    --           sequence table: 1 Element pro Überschrift
    --                           Jedes Element sequence table:
    --                                         Artikeltext
    --                                         Benutzer:Nick
    --                                         Signatur
    local h = { }
    local q = { }
    local b, p, r, s, x
    p = mw.text.split( folder():getContent(), "\n" )
    for i = 1, #p do
        s = p[ i ]
        if s:sub( 1, 2 ) == "==" then
            x, s = s:match( "^(==+) *(%S.*%S) *%1 *$" )
            if s then
                s = flat( s )
                table.insert( h, s )
                q[ s ] = { i, #h }
            end
        end
    end    -- for i
    x = false
    for k = 1, 3 do
        s = at[ k ]
        if q[ s ] then
            b = b or { }
            table.insert( b, q[ s ] )
        else
            x = x or { }
            table.insert( x, s )
        end
    end    -- for k
    if x then
        r = ""
        for i = 1, #x do
            r = string.format( "%s\n* %s %s",
                               r,
                               fault( "Überschrift nicht gefunden:" ),
                               mw.text.encode( x[ i ] ) )
        end    -- for i
        s = ""
        for i = 1, #h do
            s = string.format( "%s\n* %s",
                               s,
                               mw.text.encode( h[ i ] ) )
        end    -- for i
        x = mw.html.create( "div" )
                   :css( "font-size", "0.85em" )
                   :css( "line-height", "1em" )
                   :wikitext( s )
        r = string.format( "%s\n%s", r, tostring( x ) )
    elseif attach and b then
        table.insert( h, "" )
        table.insert( p, "" )
        if #b == 3 then
            local g = mw.language.getContentLanguage()
            local e, m, n, u
            r = { }
            for k = 1, attach  do
                e = b[ k ]
                m = e[ 1 ] + 1
                s = h[ e[ 2 ] + 1 ]
                e = q[ s ]
                if e then
                    n = e[ 1 ] - 1
                else
                    n = -1
                end
                s = ""
                for i = m, n do
                    s = string.format( "%s %s", s, p[ i ] )
                end    -- for i
                s = Frame:preprocess( s )
                if s:find( "%[%[[DdFBI]" ) then
                    e = "%[%[[DdFBI]%a:[^%]|]+%.%a+%s*|[^%]]+|[^%]]+%]%]"
                    s = s:gsub( e, "" )
                end
                e = "([^%]|]+)"
                e = "[BbUu]%l+eri?n?:" .. e
                e = "([^<]*%[%[" .. e .. " *|.+%]%][^>]*)"
                e = "%<small%>" .. e .. "%</small%>"
                e, u = s:match( e )
                if u then
                    u = string.format( "Benutzer%s:%s",
                                       g:gender( u, "", "in", "" ),
                                       u )
                end
                s = flat( s:gsub( "\n", " " ) )
                if mw.ustring.len( s )  >  MaxChars + 5 then
                    s = mw.ustring.sub( s, 1, MaxChars ) ..
                        mw.ustring.char( 0x2026 )    -- ...
                else
                    e = false
                end
                table.insert( r,  { s, u, e } )
            end    -- for k
        end
    end
    return r
end -- headlines()



local function helper( at )
    -- Zusätzliche Editierhilfe
    --     at   -- table[ 3 ]/false, Überschriften
    -- Rückgabe: string, Wikitext
    local r
    r = string.format( "[[%s]] / [%s %s]",
                       folder().prefixedText,
                       Paper:fullUrl( { action = "history" } ),
                       "Versionsgeschichte" )
    r = tostring( mw.html.create( "div" )
                         :css( "clear",      "both" )
                         :css( "padding-top", "2em" )
                         :newline()
                         :node( mw.html.create( "div" )
                                       :wikitext( r ) )
                         :newline() )
    if type( at ) == "table"  and  #at == 3 then
        local x = headlines( at, 1 )
        local s = type( x )
        if s == "string" then
            r = r .. x
        elseif s == "table" then
            x = x[ 1 ]
            if type( x ) == "table" then
                local u, e
                s = x[ 1 ]
                u = x[ 2 ]
                x = x[ 3 ]
                if u then
                    r = string.format( "%s\n; %s\n: %s",
                                       r,  u:gsub( ":", "&#58;" ),  s )
                else
                    r = string.format( "%s\n\n%s", r, s )
                end
                if x then
                    r = string.format( "%s\n\n%s", r, x )
                end
            end
        end
    end
    return r
end -- helper()



local function homepage( active )
    -- Definitionstext darstellen
    --     active   -- table[ 3 ], Definitionszeilen
    -- Rückgabe: string, Wikitext
    local p = { [ 1 ] = "syntaxhighlight",
                [ 2 ] = "",
                lang  = "text" }
    for i = 1, 3 do
        p[ 2 ] = string.format( "%s\n%s", p[ 2 ], active[ i ] )
    end    -- for i
    return Frame:callParserFunction( "#tag", p )
end -- homepage()



local function horizontal( assign, ahead, add )
    -- Eine Ticker-Zeile darstellen
    --     assign   -- string, Definitionszeile
    --     ahead    -- boolean, Kurier-Seitenkopf
    --     add      -- table, Tooltip-Elemente
    -- Rückgabe:
    --    1. string, Text
    --    2. number/false, Monat
    --    3. number/false, Tag
    --    4. string/false, Kurier-Überschrift
    local r = "\n|-\n|"
    local start, suffix = assign:match( "^(%d+%. *%d+%.)(.*)$" )
    local e, j, m, r2, scream
    if start then
        start = start:gsub( " ", "" )
        j, m = start:match( "^(%d+)%. *(%d+)%." )
        if j and m then
            j = tonumber( j )
            m = tonumber( m )
        end
        if not j  or  not m  or
           j < 1  or  j > 31  or  m < 1   or  m > 12 then
            scream = "Datum ungültig"
            m = false
            j = false
        else
            suffix = mw.text.trim( suffix )
            if suffix == "" then
                scream = "Meldungstext fehlt"
            elseif suffix:find( "[[", 1, true ) or
                   suffix:find( "|", 1, true ) or
                   suffix:find( "]]", 1, true ) then
                scream = "Wikisyntax im Meldungstext"
            else
                local max   = MaxWidthCell
                local shift = folder().prefixedText
                local style = StyleText
                local e     = mw.html.create( "span" )
                local k, show
                r = string.format( "%s%s| %s ||",
                                   r,
                                   "style='text-align:right'",
                                   start )
                k = suffix:find( "#", 2, true )
                if k then
                    k = suffix:find( "[^&]#", k - 1 )
                    if k then
                        show   = mw.text.trim( suffix:sub( 1, k ) )
                        suffix = mw.text.trim( suffix:sub( k + 2 ) )
                        if suffix == "" then
                            suffix = show
                        end
                    else
                        show = suffix
                    end
                else
                    show = suffix
                end
                if ahead then
                    e:css( "color", "#FFFFFF" )
                    max   = 200
                    if mw.title.equals( Current, folder() ) then
                        shift = ""
                    end
                elseif add then
                    local s = add[ 1 ]
                    if add[ 2 ] then
                        s = string.format( "%s +++ %s",  add[ 2 ],  s )
                    end
                    s = flat( s:gsub( "\"", "'" ) )
                    e:attr( "title", s )
                else
                    e = false
                end
                if e then
                    show  = tostring( e:wikitext( show ) )
                end
                show  = string.format( "[[%s#%s|%s]]",
                                       shift, suffix, show )
                style = string.format( "%s; max-width:%dpx;",
                                       style, max )
                r     = string.format( "%sstyle='%s'| %s",
                                       r, style, show )
                r2    = suffix
            end
        end
    else
        scream = "Kein Datum gefunden"
    end
    if scream then
        r = string.format( "%scolspan='2'|%s", r, fault( scream ) )
    end
    return r, m, j, r2
end -- horizontal()



local function howto( active )
    -- Vorlagenseite mit Dokumentation usw. ausstatten
    --     active   -- table[ 3 ], Definitionszeilen
    -- Rückgabe: string, Wikitext
    local bt = { Typ      = "progressive",
                 ["Groß"] = "1",
                 Link     = Ticker:fullUrl( { action  = "edit",
                                            summary = Summary } ),
                 Text     = "Text aktualisieren" }
    local h2 = mw.html.create( "h2" )
                      :css( "clear",      "both" )
                      :css( "margin-top", "4em" )
                      :wikitext( "Aktuelle Definition" )
    bt = Frame:expandTemplate{ title = "MediaWiki-Button",
                               args  = bt }
    return string.format( "\n%s\n%s\n%s",
                          tostring( h2 ),
                          homepage( active ),
                          bt )
end -- howto()



local function hypertext( active, ahead )
    -- Babel bzw. Tabelle darstellen
    --     active   -- table[ 3 ], Definitionszeilen
    --     ahead    -- boolean, Kurier-Seitenkopf, nur Tabelle
    -- Rückgabe:
    --     1. string, Wikitext
    --     2. table/false, Überschriften
    local r  = Frame:callParserFunction( "#tag",
                                         { [ 1 ] = "nowiki" } )
    local j0 = 99
    local m0 = 99
    local s  = StyleTable
    local t  = { }
    local h, j, m, r2
    Leader = ( Frame.args.Leader == "1" )
    if ahead then
        s = string.format( "%s; %s; %s;",
                           s,
                           "background-color:transparent",
                           "color:#FFFFFF" )
    else
        s = string.format( "%s; %s; %s;",
                           s,
                           "font-size:0.9em",
                           string.format( "max-width:%dpx",
                                          MaxWidthTable ) )
        if ( not first()  or  feeding() )   and
           not faculty( Frame:getParent().args.Low ) then
            for i = 1, 3 do
                h = active[ i ]:match( "^%d+%. *%d+%. *(.*)$" )
                if h then
                    h = h:match( "[^&]#(.+)$" )  or  h
                    table.insert( t,  mw.text.trim( h ) )
                end
            end    -- for i
            if #t == 3 then
                t = headlines( t, 3 )
                if type( t ) ~= "table"  or  #t ~= 3 then
                    t = { }
                end
            else
                t = { }
            end
        end
    end
    r = string.format( "%s\n{| style='%s'", r, s )
    for i = 1, 3 do
        s, m, j, h = horizontal( active[ i ], ahead, t[ i ] )
        if m and j then
            if m == m0 then
                if j > j0 then
                    s = fault( "Datumsabfolge falsch (Tag)" )
                end
            elseif m0 ~= 99  and
                   m ~= m0 - 1  and
                   m ~= 12  and  m0 ~= 1 then
                s = fault( "Monatsabfolge falsch" )
            end
            j0 = j
            m0 = m
        end
        if h then
            r2 = r2 or { }
            table.insert( r2, h )
        end
        if s:sub( 1, 5 ) == "<span" then
            s = "\n|-\n|colspan='2'|" .. s
        end
        r  = r .. s
    end    -- for i
    r = r .. "\n|}"
    if not ( ahead  or
             faculty( Frame:getParent().args.Light ) ) then
        local sep = mw.ustring.char( 8211 )
        s = "'''[[%s|%s]]<br /> %s<br /> [[%s|%s]]'''"
        s = string.format( s,
                           folder().prefixedText,
                           tostring( mw.html.create( "span" )
                                            :css( "color", "#FFFFFF" )
                                            :wikitext( "kurier" ) ),
                           tostring( mw.html.create( "span" )
                                            :css( "color", "#FFFFFF" )
                                            :wikitext( sep ) ),
                           Ticker.prefixedText,
                           tostring( mw.html.create( "span" )
                                            :css( "color", "#FFFFFF" )
                                            :wikitext( "ticker" ) ) )
        BabelPar.text  = r
        BabelPar.image = s
        r = Frame:expandTemplate{ title = "Benutzer aus",
                                  args  = BabelPar }
        if faculty( Frame:getParent().args.rechts )  or
           faculty( Frame:getParent().args[ 1 ] )  or
           faculty( Frame.args.rechts ) then     -- Migration
            local e = mw.html.create( "div" )
                             :addClass( "float-right" )
                             :css( "margin", "0.2em" )
                             :wikitext( r )
            r = tostring( e )
        end
    end
    return r, r2
end -- hypertext()



local function main( alt )
    -- Darstellung
    --    alt   -- boolean, Definitionstext
    local s = Frame.args.Text
    local r
    if s then
        if mw.text.trim( s ) == "" then
            s = false
        end
    elseif alt then
        if Ticker.exists then
            s = Ticker:getContent()
        end
    end
    if s then
        local o = mw.text.split( s, " *\n *" )
        local tics
        for i = 1, #o do
            if o[ i ]:find( "----", 1, true ) then
                for j = i + 1, #o do
                    if o[ j ]:find( "----", 1, true ) then
                        break   -- for j
                    else
                        s = mw.text.trim( o[ j ] )
                        if s:find( "<", 1, true ) then
                            s = s:gsub( "< *[bB][rR] */? *>", "" )
                            s = mw.text.trim( s )
                        end
                        if s ~= "" then
                            tics = tics or { }
                            table.insert( tics, s )
                        end
                    end
                end    -- for j
                break   -- for i
            end
        end    -- for i
        if tics then
            if #tics == 3 then
                if alt then
                    r = homepage( tics )
                else
                    local lead, learn, lucide, t
                    Current = mw.title.getCurrentTitle()
                    if mw.title.equals( Current.rootPageTitle,
                                        folder() ) then
                        lucide = true
                    elseif first() then
                        learn = true
                        live  = feeding()
                    end
                    r, t = hypertext( tics, lucide )
                    if live then
                        r = r .. helper( t )
                    elseif learn  and  Leader then
                        r = r .. howto( tics )
                    end
                end
            elseif #tics < 3 then
                r = fault( "ZU WENIGE TEXTZEILEN GEFUNDEN" )
            else
                r = fault( string.format( "ZU VIELE TEXTZEILEN (%d)",
                                          #tics ) )
            end
        else
            r = fault( "KEINE TEXTZEILEN GEFUNDEN" )
        end
    else
        r = fault( "KEINEN TEXT GEFUNDEN" )
    end
    if r:sub( 1, 5 ) == "<span"  and  not first() then
        r = string.format( "[[%s]] &#8211; %s", Ticker.prefixedText, r )
    end
    return r
end -- main()



-- Export
local p = { }

p.Babel = function ( frame )
    local lucky, r
    Frame = frame
    lucky, r = pcall( main )
    if not lucky then
        r = "[[Vorlage:Kurier-Ticker]] &#8211; " .. fault( r )
    end
    return r
end

p.Text = function ( frame )
    Frame = frame
    return main( true )
end

p.failsafe = function ( frame )
    return Serial
end -- p.failsafe

return p