Modul:FlagIcons

aus Wikipedia, der freien Enzyklopädie
Zur Navigation springen Zur Suche springen

Die Dokumentation für dieses Modul kann unter Modul:FlagIcons/Doku erstellt werden

local FlagIcons = { suite    = "FlagIcons",
                    serial   = "2019-07-05",
                    item     = 0,
                    settings = "config" }
--[=[
Central programming of FlagIcon templates
]=]



FlagIcons.configMap = {
    Kpx    = "number",
    parMap = "table",
    repos  = "table",
    scream = "string",
    solo   = "string",
    story  = "string"
}



local function facet( adjust )
    -- Normalize sort string
    --     adjust  -- string
    -- Returns string
    local r = adjust
    local lucky, bib = pcall( require, "Module:Sort" )
    if type( bib ) == "table" then
        r = bib.Sort().lex( r, "latin" )
    end
    return r
end -- facet()



local function faculty( adjust )
    -- Test template arg for boolean
    --     adjust  -- string or nil
    -- Returns boolean
    local s = type( adjust )
    local r
    if s == "string" then
        r = ( adjust ~= "-"  and  adjust ~= "0" )
    elseif s == "boolean" then
        r = adjust
    else
        r = false
    end
    return r
end -- faculty()



local function fault( a )
    -- Format error message by class=error
    -- Parameter:
    --     a  -- string, error message
    -- Returns:
    --     string, HTML span
    local e = mw.html.create( "span" )
                     :addClass( "error" )
                     :wikitext( a )
    return tostring( e )
end -- fault()



local function features()
    -- transclude doc page
    -- Postcondition:
    --     Returns wikitext
    local r
    if type( FlagIcons.story ) == "string" then
       local f = function ()
                     local p = { [ 1 ] = FlagIcons.select }
                     local s = FlagIcons.story
                     return  FlagIcons.frame:expandTemplate{ title = s,
                                                             args  = p }
                 end -- f()
        local lucky
        lucky, r = pcall( f )
        if not lucky then
            r = fault( r )
        end
    else
        r = fault( "FlagIcons but no doc page" )
    end
    return r
end -- features()



local function fetch( at )
    -- Create submodule page name
    -- Parameter:
    --     at  -- string, subpage name
    -- Postcondition:
    --     Returns page name
    return string.format( "%s/%s", FlagIcons.self, at )
end -- fetch()



local function fiat( apply )
    -- Build wikitext for icon and/or adjacent link
    -- Parameter:
    --     apply  -- table, repo entry
    -- Postcondition:
    --     Returns wikitext
    local shift  = FlagIcons.vals.Target or FlagIcons.vals.TargetTitle
    local show   = FlagIcons.vals.Title or FlagIcons.vals.TargetTitle
    local size   = FlagIcons.vals.WIDTHpx
    local sketch = apply.f  or  "Flag of None.svg"
    local sort   = FlagIcons.vals.SORT
    local state  = apply.a  or  "#???"
    local light  = ( shift == FlagIcons.solo )
    local lead, k, r
    if light then
        shift = state
    else
        shift = shift or state
    end
    if sort  and  sort:sub( 1, 1 ) == "@" then
        lead = true
        if #sort == 1 then
            sort = apply.s
        else
            sort = sort:sub( 2 )
        end
    end
    show = show or apply.t or state
    sort = sort or show or shift or apply.s
    if #sort  ~=  mw.ustring.len( sort ) then
        sort = facet( sort )
    end
    if lead then
        r = string.format( " data-sort-value=\"%s\"|",
                           sort:gsub( "[\"\n\t]", " " ) )
    else
        local e = mw.html.create( "span" )
                         :css( "display", "none" )
                         :wikitext( sort )
        r = tostring( e )
    end
    if size and size:match( "^%d+$" ) then
        k = tonumber( size )
        if k < 10 or k > 200 then
            k = false
        end
    end
    k = k or FlagIcons.Kpx or 20
    if apply.b then
        k = k - 2
    end
    r = string.format( "%s[[File:%s|%dpx", r, sketch, k )
    if apply.b then
        r = r .. "|border"
    end
    r = string.format( "%s|class=noviewer|link=%s|%s]]",
                       r, shift, shift )
    if not light then
        local e = mw.html.create( "span" )
        local s
        if mw.language.getContentLanguage():isRTL() then
            s = "left"
        else
            s = "right"
        end
        e:attr( "aria-hidden", "true" )
         :attr( "role", "presentation" )
         :css( "padding-" .. s, "0.6em" )
         :wikitext( r )
        if show  and  show ~= shift then
            shift = string.format( "%s|%s", shift, show )
        end
        r = string.format( "%s[[:%s]]",
                           tostring( e ), shift )
    end
    return r
end -- fiat()



local function flat( apply )
    -- Build wikitext for icon and/or adjacent link
    -- Parameter:
    --     apply  -- table, repo entry
    -- Postcondition:
    --     Returns wikitext
    local r = apply.a  or  "#???"
    if apply.t  and  apply.t ~= r then
        r = string.format( "%s|%s", r, apply.t )
    end
    r = string.format( "[[%s]]", r )
    return r
end -- flat()



local function format()
    -- Generate wikitext
    -- Postcondition:
    --     Returns wikitext, or error message
    local r, store
    if type( FlagIcons.vals.repo ) == "string" then
        store = FlagIcons.vals.repo
    elseif FlagIcons.repos then
        for k, v in pairs( FlagIcons.repos ) do
            if type( k ) == "string"  and
               mw.ustring.find( FlagIcons.select, k ) then
                if type( v ) == "string" then
                    store = v
                end
                break -- for k, v
            end
        end -- for k, v
    end
    if store then
        local lucky, repo = pcall( mw.loadData, fetch( store ) )
        if type( repo ) == "table" then
            local e = repo[ FlagIcons.select ]
            if type( e ) == "table" then
                if FlagIcons.vals.blind then
                    r = flat( e )
                else
                    r = fiat( e )
                end
            else
                local e = mw.html.create( "code" )
                                 :wikitext( FlagIcons.select )
                if type( FlagIcons.scream ) == "string" then
                    r = FlagIcons.scream
                else
                    r = "FlagIcons * no spec for %s"
                end
                if not r:find( "%s", 1, true ) then
                    r = r .. " %s"
                end
                r = fault( string.format( r, tostring( e ) ) )
            end
        else
            r = fault( tostring( repo ) )
        end
    else
        r = fault( "FlagIcons * no repo: " .. FlagIcons.select )
    end
    return r
end -- format()



local function furnish( argsF, argsT )
    -- Initialize parameters
    -- Parameter:
    --     argsF  -- table, #invoke parameters
    --     argsT  -- table, template parameters
    local cnf, lucky, s
    local f = function ( args )
                  for k, v in pairs( args ) do
                      k = tostring( k )
                      s = FlagIcons.parMap[ k ]
                      if type( s ) == "string" then
                          v = mw.text.trim( v )
                          if v ~= "" then
                              FlagIcons.vals[ s ] = v
                          end
                      --    else    UNKNOWN PAR
                      end
                  end -- for k, v
              end -- f()
    FlagIcons.self = FlagIcons.frame:getTitle()
    FlagIcons.vals = { }
    lucky, cnf = pcall( mw.loadData,  fetch( FlagIcons.settings ) )
    if type( cnf ) == "table" then
        for k, v in pairs( FlagIcons.configMap ) do
            if type( cnf[ k ] ) == v then
                FlagIcons[ k ] = cnf[ k ]
            end
        end -- for k, v
        if type( FlagIcons.parMap ) == "table" then
            f( argsF )
            f( argsT )
        end
    else
        r = fault( s )
    end
end -- furnish()



FlagIcons.failsafe = function ( atleast )
    -- Retrieve versioning and check for compliance
    -- Precondition:
    --     atleast  -- string, with required version or "wikidata"
    --                 or false
    -- Postcondition:
    --     Returns  string with appropriate version, or false
    local since = atleast
    local r
    if since == "wikidata" then
        local item = FlagIcons.item
        since = false
        if type( item ) == "number"  and  item > 0 then
            local entity = mw.wikibase.getEntity( string.format( "Q%d",
                                                                 item ) )
            if type( entity ) == "table" then
                local vsn = entity:formatPropertyValues( "P348" )
                if type( vsn ) == "table"  and
                   type( vsn.value ) == "string" and
                   vsn.value ~= "" then
                    r = vsn.value
                end
            end
        end
    end
    if not r then
        if not since  or  since <= FlagIcons.serial then
            r = FlagIcons.serial
        else
            r = false
        end
    end
    return r
end -- FlagIcons.failsafe()



-- Export
local p = { }

p.test = function ( arglist )
    local r
    FlagIcons.frame = mw.getCurrentFrame()
    furnish( arglist,  { } )
    FlagIcons.select = arglist.select or "???ID???"
    if FlagIcons.vals.doc then
        r = features()
    else
        r = format()
    end
    return r
end -- p.test()



p.f = function ( frame )
    local parent = frame:getParent()
    local scope  = parent:getTitle()
    local r
    FlagIcons.frame  = frame
    FlagIcons.select = scope:match( ":(.+)$" )
    furnish( parent.args, frame.args )
    if scope == mw.title.getCurrentTitle().prefixedText
       and not FlagIcons.vals.demo then
        r = features()
    elseif FlagIcons.select then
        r = format()
    else
        r = fault( scope )
    end
    return r
end -- p.f()



p.failsafe = function ( frame )
    -- Versioning interface
    local s = type( frame )
    local since
    if s == "table" then
        since = frame.args[ 1 ]
    elseif s == "string" then
        since = frame
    end
    if since then
        since = mw.text.trim( since )
        if since == "" then
            since = false
        end
    end
    return FlagIcons.failsafe( since )  or  ""
end -- p.failsafe()

return p