Zum Inhalt springen

Vorlage:LuaModuleDoc

Faan Wikipedia

local Serial = "2017-01-25" --[=[

  • nav()
  • failsafe()

]=]


-- Module globals local CurrentTitle local Frame


local function fetch( arg, assign )

   -- Retrieve template argument
   -- Precondition:
   --     arg     -- string or number; argument identifier
   --     assign  -- any, optional; default value
   local r = Frame.args[ arg ]
   if type( r ) ~= "string" then
       if assign == nil then
           r = "{{{<" .. arg .. ">}}}"
       else
           r = assign
       end
   end
   return r

end -- fetch()


local function catIfDefined( slot )

   -- Categorize if category defined
   --     slot  -- string; Config entry
   -- Return:
   --     string or false:  categorization, if any
   -- Uses:
   --     mw.title.makeTitle()
   local s = fetch( slot, "" )
   local r
   if #s > 0 then
       local t = mw.title.makeTitle( "Category", s )
       if t.exists then
           r = string.format( "%s", t.prefixedText )
       end
   end
   return r

end -- catIfDefined()


local function globalRepos( script )

   -- Check for global dissemination
   --     script  -- string; module name (main)
   -- Uses:
   --     fetch()
   --     >< CurrentTitle
   -- Return:
   --     string
   -- Uses:
   --     mw.wikibase.getEntity()
   --     mw.title.makeTitle()
   local entity = mw.wikibase.getEntity()
   local r
   if entity then
       local mode = 0
       local repo = entity:formatPropertyValues( "P1324" )
       local params, s, t
       if repo  and  repo.value  and  repo.value:find( "//" ) then
           repo = mw.uri.new( repo.value )
           if repo  and  repo.path:match( "^/wiki/" ) then
               local space
               space, s = repo.path:sub( 7 ):match( "^([^:]+):(.+)$" )
               if space and s then
                   t = mw.title.makeTitle( space, s )
                   s = "//" .. repo.host
                   if mw.title.equals( CurrentTitle, t )  and
                      mw.site.server:find( s, 1, true ) then
                       mode = 2
                   else
                       mode = 1
                   end
               end
           end
           s = fetch( "templateGlobal", "" )
           if #s > 0 then
               local lucky, code = pcall( require,
                                          CurrentTitle.prefixedText )
               local vsn = entity:formatPropertyValues( "P348" )
               params = { }
               if mode < 2 then
                   params[ 1 ] = string.format( "[%s %s]",
                                                tostring( repo ),
                                                repo.host )
               end
               if vsn  and  vsn.value and  vsn.value ~= "" then
                   params.version = vsn.value
               end
               if type( code ) == "table"  and  code.failsafe then
                   t = type( code.failsafe )
                   if t == "function" then
                       code = code.failsafe( { args = { } } )
                       t    = type( code )
                   else
                       code = code.failsafe
                   end
                   if t == "number" then
                       code = string.format( "%d", code )
                       t    = "string"
                   end
                   if t == "string" then
                       params.here = code
                   end
               end
               if params.version  and  params.here  and
                  params.version ~= params.here  then
                   params.update = "1"
               end
               r = Frame:expandTemplate{ title=s,
                                         args=params }
           end
       end
       s = fetch( "categoryWikiData", "" )
       if #s > 0 then
           local slot
           if mode > 0 then
               if mode == 2 then
                   slot = catIfDefined( "categoryWikiDataParent" )
               else
                   slot = catIfDefined( "categoryWikiDataChild" )
               end
           end
           if not slot then
               slot = catIfDefined( s )
           end
           if slot then
               if r then
                   r = r .. slot
               else
                   r = slot
               end
               if params and params.update then
                   slot = catIfDefined( "categoryWikiDataReplication" )
                   if slot then
                       r = r .. slot
                   end
               end
           end
       end
   end
   return r or ""

end -- globalRepos()


local function navDevelop( nsDocs, start, script )

   -- Most interesting test and development page
   -- Precondition:
   --     nsDocs  -- number; central documentation namespace number
   --     start   -- string; central documentation root
   --     script  -- string; basic module name
   -- Return:
   --     string or false:  full page name, if any
   -- Uses:
   --     mw.title.makeTitle()
   local n   = nsDocs
   local r   = false
   local sub = "/" .. fetch( "subTest", "Test" )
   local s   = string.format( "%s/%s%s", start, script, sub )
   local t   = mw.title.makeTitle( n, s )
   if not t.exists then
       local low    = false
       local subLow = mw.ustring.lower( sub )
       if subLow ~= sub then
           s   = string.format( "%s/%s%s", start, script, subLow )
           t   = mw.title.makeTitle( n, s )
           low = t.exists
       end
       if not low then
           n = mw.site.namespaces.Module.id
           s = string.format( "%s/%s", script, sub )
           t = mw.title.makeTitle( n, s )
           if not t.exists  and  subLow ~= sub then
               s = script .. subLow
               t = mw.title.makeTitle( n, s )
               t = t.exists
           end
       end
   end
   if t then
       r =  mw.site.namespaces[ n ].name .. ":" .. s
   end
   return r

end -- navDevelop()


local function navError( say, specific )

   -- Return error message, evaluate page .pageErr
   -- Precondition:
   --     say       -- string; message key
   --     specific  -- string, optional; additional information
   -- Uses:
   --     fetch()
   local show = fetch( "pageErr" )
   local r
   if type( show ) == "string" then
       local pars = { say }
       if type( specific ) == "string" then
           table.insert( pars, specific )
       end
       r = Frame:expandTemplate{ title = show, args = pars }
   else
       local e = mw.html.create( "span" )
                        :attr( "class", "error" )
                        :wikitext( error( "arg 'pageErr' missing", 3 ) )
       r = tostring( e )
   end
   return r

end -- navError()


local function navLang( suite, collect, lazy )

   -- Append languages from string to collection
   -- Precondition:
   --     suite    -- string; space separated source
   --     collect  -- table; to be extended
   --                 every element: { langCode, lazy }
   --     lazy     -- true if only existing page is to be linked
   if type( suite ) == "string" then
       local raw = mw.text.split( suite, "%s+" )
       local e, i, j, s
       for i = 1, #raw do
           s = raw[ i ]
           if #s > 1 then
               for j = 1, #collect do
                   if s then
                       e = collect[ j ]
                       if e[ 1 ] == s then
                           s = false
                           if not lazy then
                               e[ 2 ] = false
                           end
                       end
                   end
               end -- for j
               if s then
                   table.insert( collect,  { s, lazy } )
               end
           end
       end -- for i
   end

end -- navLang()


local function navLangs( nsDocs, start, script )

   -- Analyze languages
   -- Precondition:
   --     current page is supposed to transclude LuaModuleDoc
   --     nsDocs  -- number; central documentation namespace number
   --     start   -- string; central documentation root
   --     script  -- string; basic module name
   -- Return:
   --     table:  args for navigation template
   --             [1] basic module name
   --             [2] number of language codes  +  1
   --             [3] first language code
   --             [4] second language code
   --             ... list of further language codes
   -- Uses:
   --     fetch()
   --     navLang()
   --     mw.title.makeTitle()
   local e, i, s, t
   local r = { }
   local specified = fetch( "langsRequest", false )
   local super     = start .. "/" .. script .. "/"
   if type( specified ) == "string" then
       if specified:match( "^%s*$" ) then
           specified = false
       end
   end
   navLang( fetch( "langsDefault" ),  r,  specified )
   navLang( fetch( "langsMore" ),  r,  true  )
   navLang( specified, r, false )
   if #r < 1 then
       r = { { "en", false } }
   end
   for i = #r, 1, -1 do
       e = r[ i ]
       s = e[ 1 ]
       if e[ 2 ] then
           t = mw.title.makeTitle( nsDocs,  super .. s )
           if not t.exists then
               s = false
           end
       end
       if s then
           r[ i ] = s
       else
           table.remove( r, i )
       end
   end -- for i -1
   table.insert( r,  1,  script )
   table.insert( r,  2,  tostring( #r ) )
   return r

end -- navLangs()


local function navMerge( start, swift, ns, nsDocs, script, sub, lead )

   -- Include various external content into page
   -- Precondition:
   --     start   -- string; defined pageDocRoot argument
   --     swift   -- string; defined pageNav argument
   --     ns      -- number; current namespace number
   --     nsDocs  -- number; central documentation namespace number
   --     script  -- string; module name (main)
   --     sub     -- string or false; possible sub-module name
   --     lead    -- true: Module: namespace;   false: text namespace
   -- Uses:
   --     >< CurrentTitle
   --     navLangs()
   --     navError()
   --     mw.title.makeTitle()
   --     fetch()
   local server  = mw.site.server
   local super   = false
   local collect = navLangs( nsDocs, start, script )
   local t       = navDevelop( nsDocs, start, script )
   local low, r, s
   if t then
       collect.Test = t
   end
   if ns == nsDocs then
       s = string.format( "%s/%s", start, script )
       if CurrentTitle.text == s then
           super = CurrentTitle.text .. "/"
       elseif sub then
           collect.subDoc = sub
           collect.subModule = sub
           s = string.format( "%s/%s/%s", start, script, sub )
           if CurrentTitle.text == s then
               s = string.format( "%s/%s", s, collect[ 3 ] )
               t = mw.title.makeTitle( nsDocs, s )
               if t.exists then
                   super = CurrentTitle.text .. "/"
               end
           end
       end
   elseif lead and sub then
       s = string.format( "%s/%s/%s", start, script, sub )
       t = mw.title.makeTitle( nsDocs, s )
       if t.exists then
           collect.subDoc = sub
       end
   end
   if server:match( "%.beta%.wmflabs%.org$" ) then
       local slang, series = server:match( "//(%l+)%.(%l+)%." )
       low = true
       if series == "wikipedia" then
           if slang == "de" then
               collect.BETA = "w:de:"   --Talk
           end
       end
   end
   r = Frame:expandTemplate{ title = swift, args = collect }
   if not low then
       t = CurrentTitle.talkPageTitle
       if t then
           s = t.exists
       else
           s = false
       end
       if not s then
           if super then
               s = "NoTalkCentral"
           elseif ns == nsDocs + 1 then
               s = false
           else
               s = "NoTalkRedir"
           end
           if s then
               r = r .. navError( s )
           end
       end
   end
   if super then
       local d  = "{{%s*[lL]uaModuleDoc[^}]*}}%s*"
       local p1 = "^%s*" .. d .. ""
       local p2 = "%s*" .. d .. ""
       local space, sub, support
       for i = 3, #collect do
           t = mw.title.makeTitle( nsDocs,  super .. collect[ i ] )
           s = t:getContent()
           if s then
               s = s:gsub( p1, "" ):gsub( p2, "" )
               if s:match( d ) then
                   r = string.format( "%s
%s
", r, navError( "BadInclude", t.prefixedText ) ) else r = r .. Frame:expandTemplate{ title = t.prefixedText } break -- for i end end end -- for i s = fetch( "pageTemplateInsert", "" ) space, support = s:match( "^([^:]+):(.+)$" ) if space and mw.title.makeTitle( space, support ).exists then local suppress = fetch( "noHint", "" ) if #suppress == 0 then local swift = collect[ 1 ] if sub then swift = string.format( "%s/%s", swift, sub ) end r = r .. Frame:expandTemplate{ title = s, args = { swift } } end end s = fetch( "categoryDocs", "" ) if #s > 0 then i = mw.title.makeTitle( "Category", s ) if i.exists then r = string.format( "%s%s", r, i.prefixedText, collect[ 1 ] ) end end r = r .. "" end if lead then r = r .. globalRepos( script ) end return r

end -- navMerge()


local function navPage( lead, ns, nsDocs )

   -- Return navigation text; analyze page location
   -- Precondition:
   --     current namespace will support LuaModuleDoc
   --     lead    -- true: Module: namespace;   false: text namespace
   --     ns      -- number; current namespace
   --     nsDocs  -- number; namespace for doc
   -- Uses:
   --     >< CurrentTitle
   --     fetch()
   --     navError()
   --     navMerge()
   local r
   local start = fetch( "pageDocRoot" )
   if type( start ) == "string" then
       local s      = "^"
       local script
       if not lead then
           s = "^" .. start .. "/"
       end
       s = s .. "([^/]+)/(.*/?)$"
       script, s = string.match( CurrentTitle.text .. "/",  s )
       if type( script ) == "string" then
           local sub   = false
           local swift = fetch( "pageNav" )
           if type( s ) == "string" then
               if #s > 1 then
                   local q
                   s = s:match( "^([^/]+)/.*/?$" )
                   q = mw.title.makeTitle( "Module",
                                           script .. "/" .. s )
                   if q.exists and q.contentModel == "Scribunto" then
                       sub = s
                   end
               end
           end
           if type( swift ) == "string" then
               r = navMerge( start, swift, ns, nsDocs, script, sub, lead )
           else
               r = navError( "configMissing", "pageNav" )
           end
       else
           r = navError( "BadPage" ) .. CurrentTitle.text
       end
   else
       r = navError( "configMissing", "pageDocRoot" )
   end
   return r

end -- navPage()


local function navigation()

   -- Start execution; return navigation text; analyze namespace
   -- Uses:
   --     >< CurrentTitle
   --     fetch()
   --     mw.title.getCurrentTitle()
   --     navPage()
   --     navError()
   local r
   local nsDocs = fetch( "nsDocs" )
   if nsDocs then
       CurrentTitle = mw.title.getCurrentTitle()
       local ns   = CurrentTitle.namespace
       local lead = ( ns == mw.site.namespaces.Module.id )
       nsDocs = tonumber( nsDocs )
       if lead or  ns == nsDocs  or  ns == nsDocs + 1 then
           r = navPage( lead, ns, nsDocs )
       else
           r = navError( "BadNamespace" )
       end
   else
       r = navError( "configMissing", "nsDocs" )
   end
   return  r

end -- navigation()


-- Provide template access

local p = {}

function p.nav( frame )

   -- Uses:
   --     navigation()
   local lucky, r
   Frame = frame
   lucky, r = pcall( navigation )
   if not lucky then
       local e = mw.html.create( "span" )
                        :attr( "class", "error" )
                        :wikitext( r )
       r = tostring( e )
   end
   return r or ""

end

function p.failsafe()

   return Serial

end -- p.failsafe()

return p