Modul:TemplateData: Unterschied zwischen den Versionen

2019-01-03
 
imported>PerfektesChaos
2020-12-03
 
(Eine dazwischenliegende Version von einem anderen Benutzer wird nicht angezeigt)
Zeile 1: Zeile 1:
local TemplateData = { suite  = "TemplateData",
local TemplateData = { suite  = "TemplateData",
                       serial = "2019-01-03",
                       serial = "2020-12-03",
                       item  = 46997995 }
                       item  = 46997995 }
--[=[
--[=[
improve template:TemplateData
improve template:TemplateData
]=]
]=]
local Failsafe = TemplateData




Zeile 48: Zeile 49:
     got    = false,    -- table, initial templatedata object
     got    = false,    -- table, initial templatedata object
     heirs  = false,    -- table, params that are inherited
     heirs  = false,    -- table, params that are inherited
    jump    = false,    -- source position at end of "params"
     less    = false,    -- main description missing
     less    = false,    -- main description missing
     lasting = false,    -- old syntax encountered
     lasting = false,    -- old syntax encountered
Zeile 57: Zeile 59:
     scream  = false,    -- error messages
     scream  = false,    -- error messages
     sibling = false,    -- TOC juxtaposed
     sibling = false,    -- TOC juxtaposed
     slang  = false,   -- project language code
     slang  = nil,     -- project/user language code
     slim    = false,    -- JSON reduced to plain
     slim    = false,    -- JSON reduced to plain
     source  = false,    -- JSON input
     source  = false,    -- JSON input
Zeile 136: Zeile 138:




local function Fetch( ask )
local function Fetch( ask, allow )
     -- Fetch module
     -- Fetch module
     -- Parameter:
     -- Parameter:
     --    ask -- string, with name
     --    ask   -- string, with name
     --                     "/global"
     --                       "/global"
     --                     "Multilingual"
     --                       "JSONutil"
     --                     "Text"
    --                      "Multilingual"
     --                     "WLink"
     --                       "Text"
     --                       "WLink"
    --    allow  -- true: no error if unavailable
     -- Returns table of module
     -- Returns table of module
     -- error: Module not available
     -- error: Module not available
Zeile 168: Zeile 172:
             end
             end
             TemplateData.extern[ sign ] = r
             TemplateData.extern[ sign ] = r
         else
         elseif not allow then
             error( string.format( "Fetch(%s) %s", sign, g ) )
             error( string.format( "Fetch(%s) %s", sign, g ), 0 )
         end
         end
     end
     end
     return r
     return r
end -- Fetch()
end -- Fetch()
local function Foreign()
    -- Guess human language
    -- Returns slang, or not
    if type( Data.slang ) == "nil" then
        local Multilingual = Fetch( "Multilingual", true )
        if Multilingual  and
          type( Multilingual.userLangCode ) == "function" then
            Data.slang = Multilingual.userLangCode()
        else
            Data.slang = mw.language.getContentLanguage():getCode()
                                                        :lower()
        end
    end
    if Data.slang  and
      mw.ustring.codepoint( Data.slang, 1, 1 ) > 122 then
        Data.slang = false
    end
    return Data.slang
end -- Foreign()




Zeile 187: Zeile 213:
                                   :gsub( "([%-.()+*?^$%[%]])",
                                   :gsub( "([%-.()+*?^$%[%]])",
                                           "%%%1" ) )
                                           "%%%1" ) )
     local i, k = Data.source:find( seek, at )
     local i, k, r, slice, source
     local r, slice, source
    if not Data.jump then
        Data.jump = Data.source:find( "params", 2 )
        if Data.jump then
            Data.jump = Data.jump + 7
        else
            Data.jump = 1
        end
    end
     i, k = Data.source:find( seek, at + Data.jump )
     while i  and  not r do
     while i  and  not r do
         source = Data.source:sub( k + 1 )
         source = Data.source:sub( k + 1 )
Zeile 199: Zeile 233:
             r = k
             r = k
         else
         else
             i, k = Data.source:find( seek, k )
             i, k = Data.source:find( seek, k )
         end
         end
     end    -- while i
     end    -- while i
Zeile 213: Zeile 247:
     -- Returns string, with localized text
     -- Returns string, with localized text
     local o = mw.message.new( "templatedata-" .. adapt )
     local o = mw.message.new( "templatedata-" .. adapt )
     if not Data.slang then
     if Foreign() then
        local Multilingual = Fetch( "Multilingual" )
        if type( Multilingual.userLangCode ) == "function" then
            Data.slang = Multilingual.userLangCode()
        end
    end
    if Data.slang then
         o:inLanguage( Data.slang )
         o:inLanguage( Data.slang )
     end
     end
Zeile 360: Zeile 388:
     local variants = { }
     local variants = { }
     local r1, r2
     local r1, r2
    if Data.slang  and
      mw.ustring.codepoint( Data.slang, 1, 1 ) > 122 then
        Data.slang = false
    end
     for k, v in pairs( alternatives ) do
     for k, v in pairs( alternatives ) do
         if type( v ) == "string" then
         if type( v ) == "string" then
             v = mw.text.trim( v )
             v = mw.text.trim( v )
             if v ~= "" then
             if v ~= ""  and  type( k ) == "string" then
                 k = k:lower()
                 k = k:lower()
                 variants[ k ] = v
                 variants[ k ] = v
Zeile 375: Zeile 399:
     end -- for k, v
     end -- for k, v
     if n > 0 then
     if n > 0 then
         local choices, Multilingual
         local Multilingual = Fetch( "Multilingual", true )
         if n > 1 then
         if Multilingual  and
             choices = { }
          type( Multilingual.i18n ) == "function" then
        end
             local show, slang = Multilingual.i18n( variants )
        for k, v in pairs( variants ) do
             if show then
             if n == 1 then
                 r1 = show
                 r1 = v
                 variants[ slang ] = nil
            elseif Data.slang == k then
                 variants[ k ] = nil
                r1 = v
                 r2 = variants
                 r2 = variants
            else
                table.insert( choices, k )
             end
             end
         end -- for k, v
         end
         if not r1 then
         if not r1 then
             Multilingual = Fetch( "Multilingual" )
             Foreign()
             if type( Multilingual.userLang ) == "function" then
             for k, v in pairs( variants ) do
                local sel = Multilingual.userLang( choices,
                if n == 1 then
                                                  TemplateData.frame )
                    r1 = v
                r1 = variants[ sel ]
                elseif Data.slang == k then
                variants[ sel ] = nil
                    variants[ k ] = nil
                r2 = variants
                    r1 = v
             end
                    r2 = variants
                end
             end -- for k, v
         end
         end
         if r2 then
         if r2 and Multilingual then
            Multilingual = Multilingual or Fetch( "Multilingual" )
             for k, v in pairs( r2 ) do
             for k, v in pairs( r2 ) do
                 if v  and  not Multilingual.isLang( k, true ) then
                 if v  and  not Multilingual.isLang( k, true ) then
                     Fault( string.format( "Invalid <code>lang=%s</code>",
                     Fault( string.format( "%s <code>lang=%s</code>",
                                          "Invalid",
                                           k ) )
                                           k ) )
                 end
                 end
Zeile 656: Zeile 677:
             local pointers = { }
             local pointers = { }
             local points  = { }
             local points  = { }
            local given    = { }
             for k, v in pairs( Data.tree.params ) do
             for k, v in pairs( Data.tree.params ) do
                 i = facet( k, 1 )
                 i = facet( k, 1 )
                if type( v ) == "table" then
                    if type( v.label ) == "string" then
                        s = mw.text.trim( v.label )
                        if s == "" then
                            s = k
                        end
                    else
                        s = k
                    end
                    if given[ s ] then
                        if given[ s ] == 1 then
                            local scream = "Parameter label '%s' detected multiple times"
                            Fault( string.format( scream, s ) )
                            given[ s ] = 2
                        end
                    else
                        given[ s ] = 1
                    end
                end
                 if i then
                 if i then
                     table.insert( points, i )
                     table.insert( points, i )
Zeile 796: Zeile 837:
                     if type( boole.show ) == "string" then
                     if type( boole.show ) == "string" then
                         local v = mw.html.create( "span" )
                         local v = mw.html.create( "span" )
                                        :attr( "aria-hidden", "true" )
                                         :wikitext( boole.show )
                                         :wikitext( boole.show )
                         if boole.css then
                         if boole.css then
Zeile 822: Zeile 864:


     -- type
     -- type
    if type( param.type ) == "string" then
        param.type = mw.text.trim( param.type )
        if param.type == "" then
            param.type = false
        end
    end
     if param.type then
     if param.type then
         s    = Permit.types[ param.type ]
         s    = Permit.types[ param.type ]
Zeile 853: Zeile 901:
         typed = mw.html.create( "td" )
         typed = mw.html.create( "td" )
                   :wikitext( factory( "doc-param-type-unknown" ) )
                   :wikitext( factory( "doc-param-type-unknown" ) )
        Data.params[ access ].type = "unknown"
        if param.default then
            Data.params[ access ].default = nil
            Fault( "Default value requires <code>type</code>" )
            legal = false
        end
     end
     end


Zeile 889: Zeile 943:
             ranking:tag( "br" )
             ranking:tag( "br" )
             ranking:wikitext( param.deprecated )
             ranking:wikitext( param.deprecated )
        end
        if param.suggested  and  mode == 4 then
            s = string.format( "Suggesting deprecated <code>%s</code>",
                              access )
            Fault( s )
            legal = false
         end
         end
     end
     end
Zeile 998: Zeile 1.058:




local function finalize( advance )
local function fellow( any, assigned, at )
     -- Wrap presentation into frame
     -- Check sets[] parameter and issue error message, if necessary
     -- Parameter:
     -- Parameter:
     --    advance  -- true, for nice
    --    any      -- should be number
     -- Returns string
    --    assigned  -- parameter name
     local r, lapsus
    --    at        -- number, of set
     if Data.div then
    local s
    if type( any ) ~= "number" then
        s = "<code>sets[%d].params[%s]</code>??"
        Fault( string.format( s,
                              at,
                              mw.text.nowiki( tostring( any ) ) ) )
    elseif type( assigned ) == "string" then
        if not Data.got.params[ assigned ] then
            s = "<code>sets[%d].params %s</code> is undefined"
            Fault( string.format( s, at, assigned ) )
        end
    else
        s = "<code>sets[%d].params[%d] = %s</code>??"
        Fault( string.format( s,  k,  type( assigned ) ) )
    end
end -- fellow()
 
 
 
local function fellows()
    -- Check sets[] and issue error message, if necessary
    local s
    if type( Data.got.sets ) == "table" then
        if type( Data.got.params ) == "table" then
            for k, v in pairs( Data.got.sets ) do
                if type( k ) == "number" then
                    if type( v ) == "table" then
                        for ek, ev in pairs( v ) do
                            if ek == "label" then
                                s = type( ev )
                                if s ~= "string"  and
                                  s ~= "table" then
                                    s = "<code>sets[%d].label</code>??"
                                    Fault( string.format( s, k ) )
                                end
                            elseif ek == "params"  and
                                type( ev ) == "table" then
                                for pk, pv in pairs( ev ) do
                                    fellow( pk, pv, k )
                                end -- for pk, pv
                            else
                                ek = mw.text.nowiki( tostring( ek ) )
                                s  = "<code>sets[%d][%s]</code>??"
                                Fault( string.format( s, k, ek ) )
                            end
                        end -- for ek, ev
                    else
                        k = mw.text.nowiki( tostring( k ) )
                        v = mw.text.nowiki( tostring( v ) )
                        s = string.format( "<code>sets[%s][%s]</code>??",
                                          k, v )
                        Fault( s )
                    end
                else
                    k = mw.text.nowiki( tostring( k ) )
                    s = string.format( "<code>sets[%s]</code> ?????", k )
                    Fault( s )
                end
            end -- for k, v
        else
            s = "<code>params</code> required for <code>sets</code>"
            Fault( s )
        end
    else
        s = "<code>sets</code> needs to be of <code>object</code> type"
        Fault( s )
    end
end -- fellows()
 
 
 
local function finalize( advance )
    -- Wrap presentation into frame
    -- Parameter:
     --    advance  -- true, for nice
     -- Returns string
     local r, lapsus
     if Data.div then
         r = tostring( Data.div )
         r = tostring( Data.div )
     elseif Data.strip then
     elseif Data.strip then
Zeile 1.263: Zeile 1.400:
             end
             end
         end -- for k, v
         end -- for k, v
        if not access  and Data.got.sets then
            fellows()
        end
     else
     else
         Fault( f() .. " needs to be of <code>object</code> type" )
         Fault( f() .. " needs to be of <code>object</code> type" )
Zeile 1.497: Zeile 1.637:
     if s then
     if s then
         if Data.leading then
         if Data.leading then
             r:node( mw.html.create( "h2" )
             r:node( mw.html.create( "h" .. Config.nested )
                           :wikitext( factory( "doc-params" ) ) )
                           :wikitext( factory( "doc-params" ) ) )
             :newline()
             :newline()
Zeile 1.538: Zeile 1.678:
local function free()
local function free()
     -- Remove JSON comment lines
     -- Remove JSON comment lines
     Data.source:gsub( "([{,\"'])(%s*\n%s*//.*\n%s*)([},\"'])",
     if Data.source:find( "//", 1, true ) then
                      "%1%3" )
        Data.source:gsub( "([{,\"'])(%s*\n%s*//.*\n%s*)([{},\"'])",
                          "%1%3" )
    end
end -- free()
end -- free()


Zeile 1.602: Zeile 1.744:
         end
         end
     end -- for k, v
     end -- for k, v
    if arglist.heading  and  arglist.heading:match( "^[3-6]$" ) then
        Config.nested = arglist.heading
    else
        Config.nested = "2"
    end
     Config.loudly = faculty( arglist.debug or adapt.debug )
     Config.loudly = faculty( arglist.debug or adapt.debug )
     Data.lazy    = faculty( arglist.lazy )  and  not Config.loudly
     Data.lazy    = faculty( arglist.lazy )  and  not Config.loudly
Zeile 1.661: Zeile 1.808:




TemplateData.failsafe = function ( assert )
Failsafe.failsafe = function ( atleast )
     -- Retrieve versioning and check for compliance
     -- Retrieve versioning and check for compliance
     -- Precondition:
     -- Precondition:
     --    assert -- string, with required version or "wikidata",
     --    atleast -- string, with required version
     --               or false
     --                         or wikidata|item|~|@ or false
     -- Postcondition:
     -- Postcondition:
     --    Returns  string with appropriate version, or false
     --    Returns  string -- with queried version/item, also if problem
     local since = assert
    --              false   -- if appropriate
    -- 2020-08-17
    local since = atleast
     local last    = ( since == "~" )
    local linked  = ( since == "@" )
    local link    = ( since == "item" )
     local r
     local r
     if since == "wikidata" then
     if last  or  link  or  linked  or  since == "wikidata" then
         local item = TemplateData.item
         local item = Failsafe.item
         since = false
         since = false
         if type( item ) == "number"  and  item > 0 then
         if type( item ) == "number"  and  item > 0 then
             local entity = mw.wikibase.getEntity( string.format( "Q%d",
             local suited = string.format( "Q%d", item )
                                                                item ) )
            if link then
            if type( entity ) == "table" then
                r = suited
                local vsn = entity:formatPropertyValues( "P348" )
            else
                if type( vsn ) == "table"  and
                local entity = mw.wikibase.getEntity( suited )
                  type( vsn.value ) == "string" and
                if type( entity ) == "table" then
                  vsn.value ~= "" then
                    local seek = Failsafe.serialProperty or "P348"
                    r = vsn.value
                    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
                        elseif linked then
                            if mw.title.getCurrentTitle().prefixedText
                              ==  mw.wikibase.getSitelink( suited ) then
                                r = false
                            else
                                r = suited
                            end
                        else
                            r = vsn.value
                        end
                    end
                 end
                 end
             end
             end
         end
         end
     end
     end
     if not r then
     if type( r ) == "nil" then
         if not since  or  since <= TemplateData.serial then
         if not since  or  since <= Failsafe.serial then
             r = TemplateData.serial
             r = Failsafe.serial
         else
         else
             r = false
             r = false
Zeile 1.694: Zeile 1.862:
     end
     end
     return r
     return r
end -- TemplateData.failsafe()
end -- Failsafe.failsafe()
 




Zeile 1.730: Zeile 1.899:
     -- Returns string, or not
     -- Returns string, or not
     if type( adapt ) == "string" then
     if type( adapt ) == "string" then
         local lucky
         local JSONutil = Fetch( "JSONutil", true )
         Data.source = adapt
         Data.source = adapt
         free()
         free()
         lucky, Data.got = pcall( mw.text.jsonDecode, Data.source )
         if JSONutil then
         if lucky then
            local Multilingual = Fetch( "Multilingual", true )
            local f
            if Multilingual then
                f = Multilingual.i18n
            end
            Data.got = JSONutil.fetch( Data.source, true, f )
        else
            local lucky
            lucky, Data.got = pcall( mw.text.jsonDecode, Data.source )
        end
         if type( Data.got ) == "table" then
             full()
             full()
         elseif not Data.strip then
         elseif not Data.strip then
             Fault( "fatal JSON error: " .. Data.got )
            local scream = type( Data.got )
            if scream == "string" then
                scream = Data.got
            else
                scream = "Data.got: " .. scream
            end
             Fault( "fatal JSON error: " .. scream )
         end
         end
     end
     end
Zeile 1.765: Zeile 1.950:
     end
     end
     return r
     return r
end -- p.f()
end -- p.f


p.failsafe = function ( frame )
p.failsafe = function ( frame )
Zeile 1.782: Zeile 1.967:
         end
         end
     end
     end
     return TemplateData.failsafe( since )  or  ""
     return Failsafe.failsafe( since )  or  ""
end -- p.failsafe()
end -- p.failsafe


p.TemplateData = function ()
p.TemplateData = function ()