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

local Runeberg = { self   = "Vorlage:Runeberg",
                   suite  = "Runeberg",
                   serial = "2023-12-18",
                   item   = 123906537 }

--[=[
Support for templates referring to https://runeberg.org/
]=]
local Failsafe = Runeberg


if mw.site.server:find( ".beta.wmflabs.org", 4, true ) then
    require( "strict" )
end



local Data = { DBL       = { },
               NF        = { },
               Salmonsen = { },
               project   = false,
               self      = Runeberg.self,
               serial    = Runeberg.serial,
               site      = "https://runeberg.org/",
               suite     = false,
               types     = { facet   = "function",
                             figures = "function",
                             pages   = "table",
                             ranges  = "table" } }



local function range()
    -- Retrieve volume title
    -- Returns title
    local iEdt, iVol = Data.project.figures( Data )
    local r
    if iVol then
        r = Data.project.ranges[ iEdt ][ iVol ]
    else
        r = Data.fault( 10 )
    end
    return r
end -- range()



local function wwwLink()
    -- Retrieve external link from invocation
    -- Returns bracketed URL
    local iEdt, iVol, iCP, err = Data.project.figures( Data )
    local r
    if err then
        r = Data.fault( err )
    else
        local show   = Data.params.text or ""
        local site   = Data.site .. Data.suite:lower()
        local sub    = Data.params.runeberg
        local s1, s2 = Data.project.facet( Data, iEdt, iVol, iCP )
        if sub then
            if sub:match( "^%l+%.%l+$" ) then
                s2 = sub
            elseif sub:match( "^%l+$" ) then
                s2 = sub .. ".html"
            end
        end
        if s1 then
            if s2 then
                site = string.format( "%s%s/%s", site, s1, s2 )
            else
                r    = s1
                site = false
            end
        end
        if site then
            if show == "" then
                show = string.format( "%d,%d,%d",
                                      iEdt or 1,  iVol or 1,  iCP or 0 )
            end
            r = string.format( "[%s %s]", site, show )
        end
    end
    return r
end -- wwwLink()



Data.fault = function ( alert )
    local cat    = Data.params.errCat   or ""
    local class  = Data.params.errClass or ""
    local style  = Data.params.errStyle or ""
    local show   = Data.params.errText  or ""
    local suffix = type( alert )
    local e      = mw.html.create( "span" )
                          :addClass( "error" )
    local r
    if class ~= "" then
        e:addClass( class )
    end
    if style ~= "" then
        e:cssText( style )
    end
    if show == "" then
        show = "Error"
    end
    if suffix == "string" then
        show = string.format( "%s: %s", show, alert )
    elseif suffix == "number" then
        show = string.format( "%s %d", show, alert )
    end
    e:wikitext( show )
    r = tostring( e )
    if cat ~= "" then
        r = string.format( "%s[[Category:%s]]", r, cat )
    end
    return r
end -- Data.fault()



Data.fetch = function ( frame )
    -- Assign particular project
    -- Returns string with error message, or nil
    local r
    Data.frame  = frame
    Data.params = frame.args
    if Data.params.suite then
        Data.project = Data[ Data.params.suite ]
        if Data.project then
            local lucky, got, s, suite
            Data.suite = Data.params.suite
            suite = string.format( "Module:%s/%s",
                                   Data.self, Data.suite )
            lucky, got = pcall( require, suite )
            if type( got ) == "table" then
                for k, v in pairs( Data.types ) do
                    if type( got[ k ] ) == v then
                        Data.project[ k ] = got[ k ]
                    else
                        s = string.format( "%s %s '%s'",
                                           "Internal error:",
                                           "missing definition",
                                           "pages" )
                        r = Data.fault( s )
                        break -- for k, v
                    end
                end -- for k, v
            else
                s = string.format( "%s %s", "Internal error:", got )
                r = Data.fault( s )
            end
        else
            r = Data.fault( "Internal error: 'suite' unknown" )
        end
    else
        r = Data.fault( "Internal error: 'suite' is missing" )
    end
    return r
end -- Data.fetch()



Data.folio = function ( aEdt, aVol, aSub, aSplit )
    -- Retrieve web page number
    -- Returns sheet number
    local volume = Data.project.pages[ aEdt ]
    local r
    if type( volume ) == "table" then
        volume = volume[ aVol ]
        if type( volume ) == "table" then
            local k = aSub or 0
            local d
            for i = 1, #volume do
                d = volume[ i ]
                if k >= d[ 1 ]  and  k <= d[ 2 ] then
                    if d[ 4 ] then
                        if d[ 4 ] == "oddOnly" then
                            if k % 2 == 0 then
                                k = k - 1
                            end
                        end
                    elseif aSplit then
                        if k % 2 == 1 then
                            k = k + 1
                        end
                        k = k / 2
                    end
                    r = k + d[ 3 ]
                    break    -- for i
                end
            end -- i = 1, #volume
        end
    end
    return  r or 1
end -- Data.folio()



Failsafe.failsafe = function ( atleast )
    -- Retrieve versioning and check for compliance
    -- Precondition:
    --     atleast  -- string, with required version
    --                         or wikidata|item|~|@ or false
    -- Postcondition:
    --     Returns  string  -- with queried version/item, also if problem
    --              false   -- if appropriate
    -- 2020-08-17
    local since  = atleast
    local last   = ( since == "~" )
    local linked = ( since == "@" )
    local link   = ( since == "item" )
    local r
    if last  or  link  or  linked  or  since == "wikidata" then
        local item = Failsafe.item
        since = false
        if type( item ) == "number"  and  item > 0 then
            local suited = string.format( "Q%d", item )
            if link then
                r = suited
            else
                local entity = mw.wikibase.getEntity( suited )
                if type( entity ) == "table" then
                    local seek = Failsafe.serialProperty or "P348"
                    local vsn  = entity:formatPropertyValues( seek )
                    if type( vsn ) == "table"  and
                       type( vsn.value ) == "string"  and
                       vsn.value ~= "" then
                        if last  and  vsn.value == Failsafe.serial then
                            r = false
                        elseif linked then
                            if mw.title.getCurrentTitle().prefixedText
                               ==  mw.wikibase.getSitelink( suited ) then
                                r = false
                            else
                                r = suited
                            end
                        else
                            r = vsn.value
                        end
                    end
                end
            end
        end
    end
    if type( r ) == "nil" then
        if not since  or  since <= Failsafe.serial then
            r = Failsafe.serial
        else
            r = false
        end
    end
    return r
end -- Failsafe.failsafe()



-- Export
local p = { }

p.range = function ( frame )
    local r = Data.fetch( frame )
    if not r then
        r = range()
    end
    return r
end

p.wwwLink = function ( frame )
    local r = Data.fetch( frame )
    if not r then
        r = wwwLink()
    end
    return r
end

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 Failsafe.failsafe( since )  or  ""
end -- p.failsafe

setmetatable( p,  { __call = function ( func, ... )
                                 setmetatable( p, nil )
                                 return Failsafe
                             end } )

return p