Modul:Vorlage:arXiv: Unterschied zwischen den Versionen

Aus FreeWiki
Wechseln zu: Navigation, Suche
te>PerfektesChaos
(2016-02-13)
K (13 Versionen importiert)
 
(8 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
 
local Export = { suite  = "arXiv",
 
local Export = { suite  = "arXiv",
                serial = "2016-02-13" }
+
                serial = "2019-05-16",
 +
                item  = 0 }
 
--[=[
 
--[=[
 
Template:arXiv
 
Template:arXiv
Zeile 9: Zeile 10:
  
 
local Config = {
 
local Config = {
  self        = Export.suite,
+
    self        = Export.suite,
  errCat      = false,
+
    errCat      = false,
  errClass    = "error_arXiv",
+
    errClass    = "error_arXiv",
  errClasses  = false,
+
    errClasses  = false,
  errHide    = false,
+
    errHide    = false,
  errNS      = false,
+
    errNS      = false,
  errConflict = { en = "Conflict in multiple parameters",
+
    errConflict = { en = "Conflict in multiple parameters",
                  de = "Konflikt durch überbestimmte Parameter" },
+
                    de = "Konflikt durch überbestimmte Parameter" },
  errInvalid  = { en = "Invalid:",
+
    errInvalid  = { en = "Invalid:",
                  de = "Ungültig:" },
+
                    de = "Ungültig:" },
  errMissing  = { en = "Missing ID",
+
    errMissing  = { en = "Missing ID",
                  de = "ID fehlt" },
+
                    de = "ID fehlt" },
  errUnkown  = { en = "Unkown parameter:",
+
    errModule  = { en = "Library module missing:",
                  de = "Parameter unbekannt:" },
+
                    de = "Bibliotheksmodul fehlt:" },
  mode        = 0,
+
    errUnkown  = { en = "Unkown parameter:",
  showArticle = false
+
                    de = "Parameter unbekannt:" },
 +
    mode        = 0,
 +
    showArticle = false
 
}
 
}
  
Zeile 32: Zeile 35:
 
     -- Localization of messages
 
     -- Localization of messages
 
     --    apply  -- string, with message key
 
     --    apply  -- string, with message key
     -- Returns message text; at least english
+
     -- Returns message text; at least English
 +
    local entry = Config[ apply ]
 
     local r
 
     local r
    entry = Config[ apply ]
 
 
     if entry then
 
     if entry then
 +
        -- TODO: page language
 
         r = entry[ mw.language.getContentLanguage():getCode() ]
 
         r = entry[ mw.language.getContentLanguage():getCode() ]
 
         if not r then
 
         if not r then
Zeile 41: Zeile 45:
 
         end
 
         end
 
     else
 
     else
         r = string.format( "<span class=\"error\">????.%s.????</span>",
+
         r = tostring( mw.html.create( "span" )
                          apply )
+
                            :addClass( "error" )
 +
                            :wikitext( string.format( "????.%s.????",
 +
                                                      apply ) ) )
 
     end
 
     end
 
     return r
 
     return r
Zeile 65: Zeile 71:
  
  
local function fault( alert, about )
+
 
 +
local function fault( alert, about, frame )
 
     -- Format message with class="error" or similar
 
     -- Format message with class="error" or similar
 
     --    alert  -- string, with message key
 
     --    alert  -- string, with message key
 
     --    about  -- string, with explanation
 
     --    about  -- string, with explanation
 +
    --    frame  -- object
 
     -- Returns message with markup
 
     -- Returns message with markup
 +
    local scope = Config.errClass
 
     local story = factory( alert )
 
     local story = factory( alert )
 +
    local lucky, TemplUtl = pcall( require, "Module:TemplUtl" )
 
     local r, scope, style
 
     local r, scope, style
 +
    if type( TemplUtl ) == "table" then
 +
        TemplUtl = TemplUtl.TemplUtl()
 +
    end
 
     if Config.self then
 
     if Config.self then
 
         story = string.format( "%s * %s", Config.self, story )
 
         story = string.format( "%s * %s", Config.self, story )
 
     end
 
     end
     if not Config.frame then
+
     if Config.errClasses then
         Config.frame = mw.getCurrentFrame()
+
         if scope then
 +
            scope = string.format( "%s %s",
 +
                                  scope, Config.errClasses )
 +
        else
 +
            scope = Config.errClasses
 +
        end
 
     end
 
     end
     if Config.frame:preprocess( "{{REVISIONID}}" ) == "" then
+
     if about then
         Config.errCat  = false
+
         story = string.format( "%s %s", story, about )
        Config.errHide = false
 
        scope          = string.format( "%s error", Config.errClass )
 
    else
 
        scope = Config.errClass
 
 
     end
 
     end
     if Config.errHide then
+
     if type( TemplUtl ) == "table" then
        style = "style='display:none'"
+
        r = TemplUtl.failure( story,
 +
                              not Config.errHide,
 +
                              scope,
 +
                              frame )
 
     else
 
     else
         style = ""
+
         r = tostring( mw.html.create( "span" )
    end
+
                            :addClass( scope )
    if Config.errClasses then
+
                            :addClass( "error" )
        scope = string.format( "%s %s",
+
                            :wikitext( story ) )
                              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
 
     end
 
     if Config.errCat then
 
     if Config.errCat then
 
         if Config.errNS then
 
         if Config.errNS then
            local ns = mw.title.getCurrentTitle().namespace
 
 
             local st = type( Config.errNS )
 
             local st = type( Config.errNS )
 +
            local ns
 +
            if not Config.title then
 +
                Config.title = mw.title.getCurrentTitle()
 +
            end
 +
            ns = Config.title.namespace
 
             if st == "string" then
 
             if st == "string" then
 
                 local space  = string.format( ".*%%s%d%%s.*", ns )
 
                 local space  = string.format( ".*%%s%d%%s.*", ns )
Zeile 127: Zeile 142:
  
  
Export.failsafe = function ( attempt )
+
Export.failsafe = function ( ask )
     local since = attempt
+
    -- 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
 
     local r
     if since then
+
     if since == "wikidata" then
         since = mw.text.trim( since )
+
        local item = Export.item
        if since == "" then
+
         since = false
          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
 
     end
 
     end
     if since then
+
     if not r then
         if since > Export.serial then
+
         if not since  or  since <= Export.serial then
             r = ""
+
             r = Export.serial
 
         else
 
         else
             r = Export.serial
+
             r = false
 
         end
 
         end
    else
 
        r = Export.serial
 
 
     end
 
     end
 
     return r
 
     return r
Zeile 164: Zeile 192:
 
     --    .legal    true: fine
 
     --    .legal    true: fine
 
     local r = { arXiv = arXiv,
 
     local r = { arXiv = arXiv,
                 site  = "http://arxiv.org/abs/",
+
                 site  = "https://arxiv.org/abs/",
                 url  = "http://arxiv.org/abs/" .. arXiv }
+
                 url  = "https://arxiv.org/abs/" .. arXiv }
 
     local parts
 
     local parts
 
     r.legal = arXiv:match( "^[-.0-9v]+$" )
 
     r.legal = arXiv:match( "^[-.0-9v]+$" )
Zeile 257: Zeile 285:
 
     return r
 
     return r
 
end -- Export.fair()
 
end -- Export.fair()
 +
 +
 +
 +
Export.features = function ( assign )
 +
    -- Configure appearance
 +
    --    assign  -- table, with components
 +
    if type( assign ) == "table" then
 +
        for k, v in pairs( assign ) do
 +
            Config[ k ] = v
 +
        end -- for k, v
 +
    end
 +
end -- Export.features()
  
  
Zeile 275: Zeile 315:
 
                 show = arXiv.signature
 
                 show = arXiv.signature
 
             end
 
             end
             r = string.format( "[%s %s]", arXiv.url, show )
+
             r   = string.format( "[%s %s]", arXiv.url, show )
 +
            show = "arxiv"
 
             if Config.showArticle then
 
             if Config.showArticle then
                 r = string.format( "[[%s|arxiv]]:%s",
+
                 local title = mw.title.new( Config.showArticle )
                                  Config.showArticle, r )
+
                if not Config.title then
            else
+
                    Config.title = mw.title.getCurrentTitle()
                 r = string.format( "arxiv:%s", r )
+
                end
 +
                if not mw.title.equals( title, Config.title ) then
 +
                    show = string.format( "[[%s|arxiv]]",
 +
                                          Config.showArticle )
 +
                 end
 
             end
 
             end
 +
            r = string.format( "%s:%s", show, r )
 
         end
 
         end
 
         if not arXiv.legal then
 
         if not arXiv.legal then
 
             r = string.format( "%s %s ''%s''",
 
             r = string.format( "%s %s ''%s''",
                               r, fault( "errInvalid" ), arXiv.arXiv )
+
                               r,
 +
                              fault( "errInvalid", false, frame ),
 +
                              arXiv.arXiv )
 
         end
 
         end
 
     else
 
     else
Zeile 298: Zeile 346:
 
local p = { }
 
local p = { }
  
p.main = function ( argsF, argsT )
+
p.main = function ( argsF, argsT, frame )
 
     -- Invocation
 
     -- Invocation
 
     --    argsF  -- table, with #invoke parameters, or false
 
     --    argsF  -- table, with #invoke parameters, or false
 
     --    argsT  -- table, with template parameters
 
     --    argsT  -- table, with template parameters
 +
    --    frame  -- object, or nil
 
     -- Returns appropriate string, or table if argsF.mode = false
 
     -- Returns appropriate string, or table if argsF.mode = false
 
     local r
 
     local r
Zeile 337: Zeile 386:
 
                     r[ k ] = v
 
                     r[ k ] = v
 
                     k = false
 
                     k = false
                 elseif args.demo  or  faculty( args.NoCat ) then
+
                 elseif argsT.demo  or  faculty( argsT.NoCat ) then
 
                     Config.errCat  = false
 
                     Config.errCat  = false
 
                     Config.errHide = false
 
                     Config.errHide = false
Zeile 353: Zeile 402:
 
             r = string.format( "'<code>%s</code>' in Template:arXiv",
 
             r = string.format( "'<code>%s</code>' in Template:arXiv",
 
                               table.concat( unknown, " " ) )
 
                               table.concat( unknown, " " ) )
             r = fault( "errUnkown", r )
+
             r = fault( "errUnkown", r, frame )
 
         elseif ( r[ 1 ] and r.archive )  or
 
         elseif ( r[ 1 ] and r.archive )  or
 
               ( r[ 2 ] and r.id )  then
 
               ( r[ 2 ] and r.id )  then
 
             r = fault( "errConflict",
 
             r = fault( "errConflict",
                       "1= ./. archive= | 2= ./. id=" )
+
                       "1= ./. archive= | 2= ./. id=",
 +
                      frame )
 
         else
 
         else
 
             r[ 1 ] = ( r[ 1 ] or r.archive )
 
             r[ 1 ] = ( r[ 1 ] or r.archive )
Zeile 373: Zeile 423:
 
                     r[ 1 ] = r[ 2 ]
 
                     r[ 1 ] = r[ 2 ]
 
                 else
 
                 else
                     r = fault( "errMissing" )
+
                     r = fault( "errMissing", false, frame )
 
                 end
 
                 end
 
             end
 
             end
Zeile 394: Zeile 444:
 
     local lucky, r
 
     local lucky, r
 
     Config.frame = frame
 
     Config.frame = frame
     lucky, r = pcall( p.main, frame.args, frame:getParent().args )
+
     lucky, r = pcall( p.main, frame.args, frame:getParent().args, frame )
 
     if not lucky then
 
     if not lucky then
         r = string.format( "<span class=\"error\">%s * %s</span>",
+
         r = tostring( mw.html.create( "span" )
                          frame:getTitle(), r )
+
                            :addClass( "error" )
 +
                            :wikitext( string.format( "%s * %s",
 +
                                                      frame:getTitle(),
 +
                                                      r ) ) )
 
     end
 
     end
 
     return r
 
     return r
Zeile 405: Zeile 458:
  
 
p.failsafe = function ( frame )
 
p.failsafe = function ( frame )
     return Export.failsafe( frame.args[ 1 ] )
+
     -- 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()
 
end -- p.failsafe()
  

Aktuelle Version vom 6. September 2019, 12:28 Uhr

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

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



local Config = {
    self        = Export.suite,
    errCat      = false,
    errClass    = "error_arXiv",
    errClasses  = false,
    errHide     = false,
    errNS       = false,
    errConflict = { en = "Conflict in multiple parameters",
                    de = "Konflikt durch überbestimmte Parameter" },
    errInvalid  = { en = "Invalid:",
                    de = "Ungültig:" },
    errMissing  = { en = "Missing ID",
                    de = "ID fehlt" },
    errModule   = { en = "Library module missing:",
                    de = "Bibliotheksmodul fehlt:" },
    errUnkown   = { en = "Unkown parameter:",
                    de = "Parameter unbekannt:" },
    mode        = 0,
    showArticle = false
}



local function factory( apply )
    -- Localization of messages
    --     apply  -- string, with message key
    -- Returns message text; at least English
    local entry = Config[ apply ]
    local r
    if entry then
        -- TODO: page language
        r = entry[ mw.language.getContentLanguage():getCode() ]
        if not r then
            r = entry.en
        end
    else
        r = tostring( mw.html.create( "span" )
                             :addClass( "error" )
                             :wikitext( string.format( "????.%s.????",
                                                       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, frame )
    -- Format message with class="error" or similar
    --     alert  -- string, with message key
    --     about  -- string, with explanation
    --     frame  -- object
    -- Returns message with markup
    local scope = Config.errClass
    local story = factory( alert )
    local lucky, TemplUtl = pcall( require, "Module:TemplUtl" )
    local r, scope, style
    if type( TemplUtl ) == "table" then
        TemplUtl = TemplUtl.TemplUtl()
    end
    if Config.self then
        story = string.format( "%s * %s", Config.self, story )
    end
    if Config.errClasses then
        if scope then
            scope = string.format( "%s %s",
                                   scope, Config.errClasses )
        else
            scope = Config.errClasses
        end
    end
    if about then
        story = string.format( "%s %s", story, about )
    end
    if type( TemplUtl ) == "table" then
        r = TemplUtl.failure( story,
                              not Config.errHide,
                              scope,
                              frame )
    else
        r = tostring( mw.html.create( "span" )
                             :addClass( scope )
                             :addClass( "error" )
                             :wikitext( story ) )
    end
    if Config.errCat then
        if Config.errNS then
            local st = type( Config.errNS )
            local ns
            if not Config.title then
                Config.title = mw.title.getCurrentTitle()
            end
            ns = Config.title.namespace
            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.fair = function ( arXiv )
    -- Analyze code, create URL
    --     arXiv  -- string, with arXiv ID
    -- Returns table
    --     .url
    --     .site      URL of repository
    --     .scope     thematic archive until 2007
    --     .since     yymm
    --     .serial    n
    --     .sequence  version number
    --     .signature identifier within scope
    --     .legacy    true: before 2007-04-01
    --     .legal     true: fine
    local r = { arXiv = arXiv,
                site  = "https://arxiv.org/abs/",
                url   = "https://arxiv.org/abs/" .. arXiv }
    local parts
    r.legal = arXiv:match( "^[-.0-9v]+$" )
    if r.legal then
        r.serial = arXiv
    else
        parts = mw.text.split( arXiv, "/", true )
        if #parts == 2  and  parts[ 2 ] ~= "" then
            r.scope  = parts[ 1 ]
            r.serial = parts[ 2 ]
            parts = mw.text.split( r.scope, ".", true )
            if #parts <= 2 then
                local p = mw.text.split( parts[ 1 ], "-", true )
                if #p <= 2 then
                    r.legal = p[ 1 ]:match( "^%l+$" )
                    if r.legal  and  #p == 2 then
                        r.legal = p[ 2 ]:match( "^%l+$" )
                    end
                    if r.legal  and  #parts == 2 then
                        r.legal = parts[ 2 ]:match( "^%l+$" )   or
                                  parts[ 2 ]:match( "^%u%u$" )
                    end
                end
            end
        end
    end
    if r.legal and r.serial then
        parts = mw.text.split( r.serial, "v", true )
        if #parts > 1 then
            r.serial   = parts[ 1 ]
            r.sequence = parts[ 2 ]
            r.legal    = ( #parts == 2   and
                           r.sequence:match( "^[1-9]%d*$" ) )
        end
        if r.legal then
            local split = "^([0129]%d)([01]%d)[.]?(%d+)$"
            local j, m, n = r.serial:match( split )
            r.legal = n
            if r.legal then
                r.since  = j .. m
                r.serial = n
                m        = tonumber( m )
                r.legal  = ( m <= 12 )
                if r.legal then
                    j = tonumber( j )
                    if j < 90 then
                        r.legal = ( j <= tonumber( os.date( "%y" ) ) )
                    end
                    if r.legal then
                        local k = 5
                        local scheme
                        r.legacy = ( j > 90   or
                                     j < 7    or
                                     ( j == 7  and  m < 4 ) )
                        if r.legacy then
                            k = 3
                        elseif j < 15 then
                            k = 4
                        end
                        n        = tonumber( n )
                        scheme   = string.format( "%%0%dd", k )
                        r.serial = string.format( scheme, n )
                        r.legal  = ( r.serial:len() == k )
                        if r.legacy  and  not r.scope then
                            r.legal = false
                        end
                    end
                end
            end
        end
    end
    if r.legal then
        r.signature = r.since
        if not r.legacy then
            r.signature = r.signature .. "."
        end
        r.signature = r.signature .. r.serial
        if r.sequence then
            r.signature = string.format( "%sv%s",
                                         r.signature, r.sequence )
        end
        if r.legacy then
            r.signature = string.format( "%s/%s", r.scope, r.signature )
        end
        r.url = r.signature
    else
        r.signature = arXiv
        r.url       = r.signature
    end
    r.url = r.site .. r.url
    return r
end -- Export.fair()



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



Export.format = function ( arXiv )
    -- Format template request
    --     arXiv  -- table, with result of analysis
    -- May be influenced by Config.mode (0: standard appearance).
    -- Returns appropriate string
    local r
    if type( arXiv ) == "table" then
        local show
        if Config.mode == 0  or  true then
            if arXiv.scope   and  not arXiv.legacy then
                show = string.format( "%s&#160;&#91;%s&#93;",
                                      arXiv.signature, arXiv.scope )
            else
                show = arXiv.signature
            end
            r    = string.format( "[%s %s]", arXiv.url, show )
            show = "arxiv"
            if Config.showArticle then
                local title = mw.title.new( Config.showArticle )
                if not Config.title then
                    Config.title = mw.title.getCurrentTitle()
                end
                if not mw.title.equals( title, Config.title ) then
                    show = string.format( "[[%s|arxiv]]",
                                          Config.showArticle )
                end
            end
            r = string.format( "%s:%s", show, r )
        end
        if not arXiv.legal then
            r = string.format( "%s %s ''%s''",
                               r,
                               fault( "errInvalid", false, frame ),
                               arXiv.arXiv )
        end
    else
        r = "Module:Template:arXiv::format() no table arg"
    end
    return r
end -- Export.format()



-- Export
local p = { }

p.main = function ( argsF, argsT, frame )
    -- Invocation
    --     argsF  -- table, with #invoke parameters, or false
    --     argsT  -- table, with template parameters
    --     frame  -- object, or nil
    -- Returns appropriate string, or table if argsF.mode = false
    local r
    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 <= 2 ) then
                    r[ k ] = mw.text.trim( v )
                    k = false
                else
                    k = tostring( k )
                end
            elseif s == "string" then
                if k == "id"  or
                   k == "archive" then
                    r[ k ] = v
                    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:arXiv",
                               table.concat( unknown, " " ) )
            r = fault( "errUnkown", r, frame )
        elseif ( r[ 1 ] and r.archive )  or
               ( r[ 2 ] and r.id )   then
            r = fault( "errConflict",
                       "1= ./. archive= | 2= ./. id=",
                       frame )
        else
            r[ 1 ] = ( r[ 1 ] or r.archive )
            r[ 2 ] = ( r[ 2 ] or r.id )
            if r[ 1 ] == "" then
                r[ 1 ] = false
            end
            if r[ 2 ] == "" then
                r[ 2 ] = false
            end
            if r[ 1 ] and r[ 2 ] then
                r[ 1 ] = string.format( "%s/%s", r[ 1 ], r[ 2 ] )
            elseif not r[ 1 ] then
                if r[ 2 ] then
                    r[ 1 ] = r[ 2 ]
                else
                    r = fault( "errMissing", false, frame )
                end
            end
        end
    else
        r = false
    end
    if type( r ) == "table" then
        r = Export.fair( r[ 1 ] )
        if Config.mode then
            r = Export.format( r )
        end
    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, frame )
    if not lucky then
        r = tostring( mw.html.create( "span" )
                             :addClass( "error" )
                             :wikitext( string.format( "%s * %s",
                                                       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.arXiv = function ()
    return Export
end -- p.arXiv()

return p