Modul:Vorlage:LuaModuleDoc

Aus FreeWiki
Version vom 1. November 2019, 17:29 Uhr von te>PerfektesChaos (2019-10-30)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

local LuaModuleDoc = { suite = "LuaModuleDoc",

                      serial = "2019-10-30",
                      item   = 12981914,
                      frame  = false,
                      ns     = -9999,
                               -- current namespace number
                      nsDocs = -99999,
                               -- central documentation namespace number
                      title  = false,
                               -- current page Title object
                      transl = false }

--[=[ Support Lua-Fehler: Der Prozess konnte nicht erstellt werden: proc_open(/dev/null): failed to open stream: Operation not permitted

  • nav()
  • failsafe()

]=] local Failsafe = LuaModuleDoc


local function fetch( arg, assign )

   -- Retrieve template argument
   -- Precondition:
   --     arg     -- string or number; argument identifier
   --     assign  -- any, optional; default value
   -- Uses:
   --     >  LuaModuleDoc.frame
   local r = LuaModuleDoc.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 createPage( swift, sub, start, ns, script )

   -- Create button for page creation
   --     swift   -- string;
   --                "NoPageCentral", "NoTalkCentral", "NoTalkRedir"
   --     sub     -- string; page name to be created
   --     start   -- string; defined pageDocRoot argument
   --     ns      -- number; namespace
   --     script  -- string; module name (main)
   -- Return:
   --     string
   -- Uses:
   --     >  LuaModuleDoc.frame
   --     fetch()
   -- MediaWiki:Move-leave-redirect   Weiterleitung erstellen
   -- MediaWiki:autosumm-new          Seite wurde neu angelegt: „$1“
   local setup = "preload" .. swift:sub( 7 )
   local r
   setup = fetch( setup )
   if setup then
       local create = { action  = "edit",
                        preload = setup,
                        redlink = "1" }
       local button, path, show, story, summary
       if swift == "NoTalkRedir" then
           show    = "move-leave-redirect"
           story   = string.format( "%s/%s", start, script )
           story   = mw.title.makeTitle( ns, story ).prefixedText
           story   = string.format( "%s", story )
           summary = "#redirect " .. story
       else
           local s = fetch( "langsRequest", false )
           show    = "recreate"
           if s then
               s = mw.text.trim( s )
               if s ~= "" then
                   s = "|" .. s
               end
           end
           story = ( s or "" )
           summary = "Lua-Fehler: Der Prozess konnte nicht erstellt werden: proc_open(/dev/null): failed to open stream: Operation not permitted"
       end
   --  summary = mw.message.new( "autosumm-new" ):params( summary )
       create.summary      = summary
       create.preloadtitle = summary
       if story then
           create[ "preloadparams[]" ] = story
       end
       path   = { sub,  mw.uri.buildQueryString( create ) }
       r      = LuaModuleDoc.frame:callParserFunction( "fullurl", path )
       show   = mw.message.new( show ):plain()
       button = mw.title.makeTitle( mw.site.namespaces.Template.id,
                                    "MediaWiki-Button" )
       if button.exists then
           button = { template = button.text,
                      Typ      = "progressive",
                      ["Groß"] = "1",
                      Link     = r,
                      Text     = show }
           r      = LuaModuleDoc.frame:expandTemplate{
                                                title = button.template,
                                                args  = button }
       else
           r = string.format( "
[%s %s]", r, show ) end end return r or ""

end -- createPage()


local function globalRepos( script )

   -- Check for global dissemination
   --     script  -- string; module name (main)
   -- Uses:
   --     >  LuaModuleDoc.title
   --     >  LuaModuleDoc.frame
   --     fetch()
   --     mw.wikibase.getEntity()
   --     mw.title.makeTitle()
   -- Return:
   --     string
   local entity = mw.wikibase.getEntity()
   local r
   if type( entity ) == "table" then
       local mode = 0
       local repo = entity:formatPropertyValues( "P1324" )
       local params, s
       if type( repo ) == "table"  and
          type( repo.value) == "string"  and
          repo.value:find( "//" ) then
           local t = mw.text.split( repo.value, ",%s+" )
           if #t > 1 then
               for i = 1, #t do
                   if t[ i ]:find( mw.site.server, 1, true ) then
                       s = t[ i ]
                       break -- for i
                   end
               end -- for i
               if not s then
                   s = t[ 1 ]
               end
           else
               s = repo.value
           end
           repo = mw.uri.new( s )
           if type( repo.path ) == "string"  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( LuaModuleDoc.title, 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 l, bib = pcall( require,
                                     LuaModuleDoc.title.prefixedText )
               local vsn = entity:formatPropertyValues( "P348" )
               params = { }
               if mode < 2 then
                   params[ 1 ] = string.format( "[%s %s]",
                                                tostring( repo ),
                                                repo.host )
               end
               if type( vsn ) == "table"  and
                  type( vsn.value) == "string" and
                  vsn.value ~= "" then
                   params.version = vsn.value
               end
               if type( bib ) == "table" then
                   local serial
                   if bib.failsafe then
                       if type( bib.failsafe ) == "function" then
                           serial = bib.failsafe( { args = { } } )
                       else
                           serial = bib.failsafe
                       end
                   elseif bib[ "#serial"] then
                       serial = bib[ "#serial"]
                   end
                   if type( serial ) == "number" then
                       serial = string.format( "%d", serial )
                   end
                   if type( serial ) == "string" then
                       params.here = serial
                   end
               end
               if fetch( "forkedGlobal", "0" ) ~= "1"  and
                  params.version  and  params.here  and
                  params.version ~= params.here  then
                   params.update = "1"
               end
               r = LuaModuleDoc.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( start, script )

   -- Most interesting test and development page
   -- Precondition:
   --     start   -- string; central documentation root
   --     script  -- string; basic module name
   -- Return:
   --     string or false:  full page name, if any
   -- Uses:
   --     >  LuaModuleDoc.nsDocs
   --     mw.title.makeTitle()
   local n   = LuaModuleDoc.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 = string.format( "%s:%s",
                          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:
   --     >  LuaModuleDoc.frame
   --     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 = LuaModuleDoc.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( start, script )

   -- Analyze languages
   -- Precondition:
   --     current page is supposed to transclude LuaModuleDoc
   --     start   -- string; central documentation root
   --     script  -- string; basic module name
   -- Postcondition:
   --     LuaModuleDoc.transl is set up as 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:
   --     >  LuaModuleDoc.nsDocs
   --      < LuaModuleDoc.transl
   --     fetch()
   --     navLang()
   --     mw.title.makeTitle()
   local e, i, s, t
   local specified = fetch( "langsRequest", false )
   local super     = start .. "/" .. script .. "/"
   LuaModuleDoc.transl = { }
   if type( specified ) == "string" then
       if specified:match( "^%s*$" ) then
           specified = false
       end
   end
   navLang( fetch( "langsDefault" ),  LuaModuleDoc.transl,  specified )
   navLang( fetch( "langsMore" ),  LuaModuleDoc.transl,  true  )
   navLang( specified, LuaModuleDoc.transl, false )
   if #LuaModuleDoc.transl < 1 then
       LuaModuleDoc.transl = { { "en", false } }
   end
   for i = #LuaModuleDoc.transl, 1, -1 do
       e = LuaModuleDoc.transl[ i ]
       s = e[ 1 ]
       if e[ 2 ] then
           t = mw.title.makeTitle( LuaModuleDoc.nsDocs,  super .. s )
           if not t.exists then
               s = false
           end
       end
       if s then
           LuaModuleDoc.transl[ i ] = s
       else
           table.remove( LuaModuleDoc.transl, i )
       end
   end -- for i -1
   table.insert( LuaModuleDoc.transl,
                 1,
                 script )
   table.insert( LuaModuleDoc.transl,
                 2,
                 tostring( #LuaModuleDoc.transl ) )

end -- navLangs()


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

   -- Include various external content into page
   -- Precondition:
   --     start   -- string; defined pageDocRoot argument
   --     swift   -- string; defined pageNav argument
   --     script  -- string; module name (main)
   --     sub     -- string or false; possible sub-module name
   --     lead    -- true: Module: namespace;   false: text namespace
   -- Uses:
   --     >  LuaModuleDoc.transl
   --     >  LuaModuleDoc.ns
   --     >  LuaModuleDoc.nsDocs
   --     >  LuaModuleDoc.title
   --     >  LuaModuleDoc.frame
   --     navError()
   --     mw.title.makeTitle()
   --     createPage()
   --     fetch()
   local server = mw.site.server
   local super  = false
   local t      = navDevelop( start, script )
   local collect, low, r, s
   collect = LuaModuleDoc.transl
   if t then
       collect.Test = t
   end
   if LuaModuleDoc.ns == LuaModuleDoc.nsDocs then
       s = string.format( "%s/%s", start, script )
       if LuaModuleDoc.title.text == s then
           super = LuaModuleDoc.title.text .. "/"
       elseif sub then
           collect.subDoc = sub
           collect.subModule = sub
           s = string.format( "%s/%s/%s", start, script, sub )
           if LuaModuleDoc.title.text == s then
               s = string.format( "%s/%s", s, collect[ 3 ] )
               t = mw.title.makeTitle( LuaModuleDoc.nsDocs, s )
               if t.exists then
                   super = LuaModuleDoc.title.text .. "/"
               end
           end
       end
   elseif lead and sub then
       s = string.format( "%s/%s/%s", start, script, sub )
       t = mw.title.makeTitle( LuaModuleDoc.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 = LuaModuleDoc.frame:expandTemplate{ title = swift,
                                          args = collect }
   if not low then
       t = LuaModuleDoc.title.talkPageTitle
       if LuaModuleDoc.ns == mw.site.namespaces.Module.id then
           local doc
           s   = string.format( "%s/%s", start, script )
           doc = mw.title.makeTitle( LuaModuleDoc.nsDocs, s )
           if not doc.exists then
               r = r .. createPage( "NoPageCentral",
                                    doc.prefixedText,
                                    start,
                                    LuaModuleDoc.nsDocs,
                                    script )
               t = false
           end
       end
       if t  and  not t.exists then
           if super then
               s = "NoTalkCentral"
           elseif LuaModuleDoc.ns == LuaModuleDoc.nsDocs + 1 then
               s = false
           else
               s = "NoTalkRedir"
           end
           if s then
               r = string.format( "%s%s%s",
                                  r,
                                  navError( s ),
                                  createPage( s,
                                              t.prefixedText,
                                              start,
                                              LuaModuleDoc.nsDocs + 1,
                                              script ) )
           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( LuaModuleDoc.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 .. LuaModuleDoc.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 .. LuaModuleDoc.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 )

   -- Return navigation text; analyze page location
   -- Precondition:
   --     current namespace will support LuaModuleDoc
   --     lead    -- true: Module: namespace;   false: text namespace
   -- Uses:
   --     >  LuaModuleDoc.title
   --     >  LuaModuleDoc.transl
   --     fetch()
   --     navLangs()
   --     navMerge()
   --     navError()
   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( LuaModuleDoc.title.text .. "/",  s )
       if type( script ) == "string" then
           local sub   = false
           local swift = fetch( "pageNav" )
           navLangs( start, script )
           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
                       for i = 1, #LuaModuleDoc.transl do
                           if LuaModuleDoc.transl[ i ] == s then
                               sub = false
                               break    -- for i
                           end
                       end -- for i
                   end
               end
           end
           if type( swift ) == "string" then
               r = navMerge( start,
                             swift,
                             script,
                             sub,
                             lead )
           else
               r = navError( "configMissing", "pageNav" )
           end
       else
           r = navError( "BadPage" ) .. LuaModuleDoc.title.text
       end
   else
       r = navError( "configMissing", "pageDocRoot" )
   end
   return r

end -- navPage()


local function navigation()

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

end -- navigation()


Failsafe.failsafe = function ( atleast )

   -- Retrieve versioning and check for compliance
   -- Precondition:
   --     atleast  -- string, with required version or "wikidata" or "~"
   --                 or false
   -- Postcondition:
   --     Returns  string  -- with queried version, also if problem
   --              false   -- if appropriate
   -- 2019-10-15
   local last  = ( atleast == "~" )
   local since = atleast
   local r
   if last  or  since == "wikidata" then
       local item = Failsafe.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 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
                   else
                       r = vsn.value
                   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()


-- Provide template access local p = {}

function p.nav( frame )

   -- Uses:
   --      < LuaModuleDoc.frame
   --     navigation()
   local lucky, r
   LuaModuleDoc.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


p.failsafe = function ( frame )

   -- Check or retrieve version information
   -- Precondition:
   --     frame  -- object; #invoke environment
   -- Postcondition:
   --     Return string with error message or ""
   -- Uses:
   --     LuaModuleDoc.failsafe()
   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()

return p