Modul:Vorlage:arXiv

Aus FreeWiki
Version vom 3. Januar 2016, 19:14 Uhr von te>PerfektesChaos (Setup)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

local Serial = "2016-01-03" --[=[ Template:arXiv and other issues dealing with arXiv ID. ]=]


local Config = {

  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" },
  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 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( "????.%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 fair( arXiv )

   -- Analyze code
   --     arXiv  -- string, with message key
   -- Returns table
   --     .url
   --     .scope    thematic archive until 2007
   --     .serial   digits
   --     .legal    true: fine
   local r = { arXiv = arXiv,
               url   = "http://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
       local sub = r.serial
       parts = mw.text.split( r.serial, "v", true )
       if #parts > 1 then
           r.legal = ( #parts == 2   and
                       parts[ 2 ]:match( "^[1-9]%d*$" ) )
           sub     = parts[ 1 ]
       end
       if r.legal then
           if r.scope then
               r.legal = sub:match( "^%d+$" )
           else
               local y, m = sub:match( "^([0-2]%d)([01]%d)%.%d+$" )
               r.legal = ( y and
                           tonumber( y ) >= 7   and
                           tonumber( m ) <= 12 )
           end
       end
   end
   return r

end -- fair()


local function fault( alert )

   -- Format message with class="error" or similar
   --     alert  -- string, with message key
   -- Returns message with markup
   local story = factory( alert )
   local r, scope, style
   if not Config.frame then
       Config.frame = mw.getCurrentFrame()
   end
   if Config.frame:preprocess( "4043" ) == "" 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( "%s",
                      scope, style, story )
   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", r, Config.errCat )
       end
   end
   return r

end -- fault()


local function format( 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
           show = arXiv.serial
           if arXiv.scope then
               show = string.format( "%s/%s", arXiv.scope, show )
           end
           r = string.format( "[%s %s]", arXiv.url, show )
           if Config.showArticle then
               r = string.format( "arxiv:%s",
                                  Config.showArticle, r )
           else
               r = string.format( "arxiv:%s", r )
           end
       end
       if not arXiv.legal then
           r = string.format( "%s %s %s",
                              r,  fault( "errInvalid" ),  arXiv.arXiv )
       end
   else
       r = "Module:Template:arXiv::format() no table arg"
   end
   return r

end -- 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
   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 args.demo  or  faculty( args.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( "'%s' in Template:arXiv",
                              table.concat( unknown, " " ) )
           r = fault( "errUnkown", r )
       elseif ( r[ 1 ] and r.archive )  or
              ( r[ 2 ] and r.id )   then
           r = fault( "errConflict", r )
       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", r )
               end
           end
       end
   else
       r = false
   end
   if type( r ) == "table" then
       r = fair( r[ 1 ] )
       if Config.mode then
           r = 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 )
   if not lucky then
       r = string.format( "%s * %s",
                          frame:getTitle(), r )
   end
   return r

end -- p.f()


p.failsafe = function ()

   return Serial

end -- p.failsafe()


p.format = function ( arXiv )

   return format( arXiv )

end -- p.format()

return p