Modul:Vorlage:bibcode

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

local Export = { suite  = "bibcode",
                 serial = "2019-05-16",
                 item   = 0 }
--[=[
Template:bibcode
and other issues dealing with bibcode ID.
]=]



local Config = {
   self          = Export.suite,
   errCat        = false,
   errClass      = "error_bibcode",
   errClasses    = false,
   errHide       = false,
   errNS         = false,
   errEncodedURL = { en = "ID with undesirable URL encoding",
                     de = "ID mit unerwünschtem [[URL-Encoding]]" },
   errInvalid    = { en = "Invalid:",
                     de = "Ungültig:" },
   errLength     = { en = "ID with bad length:",
                     de = "ID mit ungültiger Länge:" },
   errMissing    = { en = "Missing ID",
                     de = "ID fehlt" },
   errUnkown     = { en = "Unkown parameter:",
                     de = "Parameter unbekannt:" },
   mode          = 0,
   showArticle   = "Bibcode",
   site          = "https://ui.adsabs.harvard.edu/abs/",
   supply        = { en = "full text available",
                     de = "Volltext verfügbar" }
}



local function factory( apply )
    -- Localization of messages
    --     apply  -- string, with message key
    -- Returns message text; at least english
    local r
    entry = Config[ apply ]
    if entry then
        r = entry[ mw.language.getContentLanguage():getCode() ]
        if not r then
            r = entry.en
        end
    else
        r = string.format( "<span class=\"error\">????.%s.????</span>",
                           apply )
    end
    return r
end -- factory()



local function faculty( adjust )
    -- Test template arg for boolean
    --     adjust  -- string or nil
    -- Returns boolean
    local r = false
    if adjust then
        r = mw.text.trim( adjust )
        if r ~= ""  and  r ~= "0" then
            r = true
        end
    end
    return r
end -- faculty()



local function fault( alert, about )
    -- Format message with class="error" or similar
    --     alert  -- string, with message key
    --     about  -- string, with explanation
    -- Returns message with markup
    local story = factory( alert )
    local r, scope, style
    if Config.self then
        story = string.format( "%s * %s", Config.self, story )
    end
    if not Config.frame then
        Config.frame = mw.getCurrentFrame()
    end
    if Config.frame:preprocess( "{{REVISIONID}}" ) == "" then
        Config.errCat  = false
        Config.errHide = false
        scope          = string.format( "%s error", Config.errClass )
    else
        scope = Config.errClass
    end
    if Config.errHide then
        style = "style='display:none'"
    else
        style = ""
    end
    if Config.errClasses then
        scope = string.format( "%s %s",
                               scope, Config.errClasses )
    end
    r = string.format( "<span class=\"%s\" %s>%s</span>",
                       scope, style, story )
    if about then
        r = string.format( "%s %s", r, about )
    end
    if Config.errCat then
        if Config.errNS then
            local ns = mw.title.getCurrentTitle().namespace
            local st = type( Config.errNS )
            if st == "string" then
                local space  = string.format( ".*%%s%d%%s.*", ns )
                local spaces = string.format( " %s ", Config.errNS )
                if spaces:match( space ) then
                    Config.errNS = false
                end
            elseif st == "table" then
                for i = 1, #Config.errNS do
                    if Config.errNS[ i ] == ns then
                        Config.errNS = false
                        break    -- for i
                    end
                end -- for i
            end
        end
        if not Config.errNS then
            r = string.format( "%s[[Category:%s]]", r, Config.errCat )
        end
    end
    return r
end -- fault()



Export.failsafe = function ( ask )
    -- Retrieve versioning and check for compliance
    -- Precondition:
    --     ask  -- string, with required version or "wikidata", or false
    -- Postcondition:
    --     Returns  string with appropriate version, or false
    local since = ask
    local r
    if since == "wikidata" then
        local item = Export.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 <= Export.serial then
            r = Export.serial
        else
            r = false
        end
    end
    return r
end -- Export.failsafe()



Export.features = function ( assign )
    -- Configure appearance
    --     assign  -- table, with components
    if type( assign ) == "table" then
        for k, v in pairs( assign ) do
            assign[ k ] = v
        end -- for k, v
    end
end -- Export.features()



Export.format = function ( article, all )
    -- Analyze code, create URL, format
    --     article  -- string, with bibcode ID
    --     all      -- full version available
    --                 true or string with details
    -- Returns string, with external link or error message
    local scan   = "^([12][05-9]%d%d)%a[0-9a-zA-Z.&]+%%?$"
    local serial = article
    local s = type( article )
    local legal, less, r
    if s ~= "string" then
        -- Work-around; 2016-02 strange things
        if s == "table" then
            serial = article[ 1 ]
        else
            serial = tostring( serial )
        end
        mw.log( "bibcode.format() 2016-02", s, article )
    end
    legal = serial:match( scan )
    if not legal then
        less = serial:match( "%%%x%x" )
        if less then
            serial = mw.uri.decode( serial )
            legal  = serial:match( scan )
        end
    end
    if legal then
        legal = ( tonumber( legal ) <= tonumber( os.date( "%Y" ) ) )
    end
    if legal then
        if #serial == 19 then
            r = string.format( "[%s%s %s]",
                               Config.site, serial, serial )
            if Config.showArticle then
                r = string.format( "[[%s|bibcode]]:%s",
                                   Config.showArticle, r )
            else
                r = "bibcode:" .. r
            end
            if less then
                r = string.format( "%s %s",
                                   r,  fault( "errEncodedURL" ) )
            end
            if all then
                local suffix = factory( "supply" )
                if type( all ) == "string" then
                    suffix = string.format( "%s&#160;/ %s", suffix, all )
                end
                r = string.format( "%s (%s)", r, suffix )
            end
        else
            r = string.format( "%s ''%s''",
                               fault( "errLength" ),  serial )
        end
    else
        r = string.format( "%s ''%s''",
                           fault( "errInvalid" ),  serial )
    end
    return r
end -- Export.format()



-- Export
local p = { }

p.main = function ( argsF, argsT )
    -- Invocation
    --     argsF  -- table, with #invoke parameters, or false
    --     argsT  -- table, with template parameters
    -- Returns appropriate string, or table if argsF.mode = false
    local r, stuff, suffix
    if argsF then
        Config.errCat     = argsF.errCat
        Config.errClasses = argsF.errClasses
        Config.errHide    = faculty( argsF.errHide )
        Config.errNS      = argsF.errNS
        if argsF.mode ~= nil then
            Config.mode = argsF.mode
        end
        if argsF.showArticle ~= nil then
            if argsF.showArticle == "" then
                Config.showArticle = false
            else
                Config.showArticle = argsF.showArticle
            end
        end
    end
    if type( argsT ) == "table" then
        local unknown
        r = { }
        for k, v in pairs( argsT ) do
            s = type( k )
            if s == "number" then
                if ( k == 1 ) then
                    stuff = mw.text.trim( v )
                    if ( stuff == "" ) then
                        stuff = false
                    end
                    k = false
                else
                    k = tostring( k )
                end
            elseif s == "string" then
                if argsT.full then
                    if ( argsT.full == "" ) then
                        suffix = true
                    else
                        suffix = argsT.full
                    end
                    k = false
                elseif argsT.demo  or  faculty( argsT.NoCat ) then
                    Config.errCat  = false
                    Config.errHide = false
                    k = false
                end
            end
            if k then
                if not unknown then
                    unknown = { }
                end
                table.insert( unknown, k )
            end
        end -- for k, v
        if unknown then
            r = string.format( "'<code>%s</code>' in Template:bibcode",
                               table.concat( unknown, " " ) )
            r = fault( "errUnkown", r )
        elseif not stuff then
            r = fault( "errMissing" )
        end
    else
        r = false
    end
    if type( r ) == "table" then
        r = Export.format( stuff, suffix )
    end
    return r
end -- p.main()



p.f = function ( frame )
    local lucky, r
    Config.frame = frame
    lucky, r = pcall( p.main, frame.args, frame:getParent().args )
    if not lucky then
        r = string.format( "<span class=\"error\">%s * %s</span>",
                           frame:getTitle(), r )
    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 Export.failsafe( since )  or  ""
end -- p.failsafe()



p.bibcode = function ()
    return Export
end -- p.bibcode()

return p