Modul:TemplateData: Unterschied zwischen den Versionen

w>PerfektesChaos
2019-05-18
K 78 Versionen von skanwiki:Modul:TemplateData importiert
 
(19 dazwischenliegende Versionen von 5 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
local TemplateData = { suite  = "TemplateData",
local TemplateData = { suite  = "TemplateData",
                       serial = "2019-05-18",
                       serial = "2021-07-05",
                       item  = 46997995 }
                       item  = 46997995 }
--[=[
--[==[
improve template:TemplateData
improve template:TemplateData
]=]
]==]
local Failsafe = TemplateData




Zeile 12: Zeile 13:
     basicCnf = { catProblem    = "strange",
     basicCnf = { catProblem    = "strange",
                 classNoNumTOC = "suppressTOCnum",
                 classNoNumTOC = "suppressTOCnum",
                classTable    = "classTable",
                 cssParWrap    = "cssTabWrap",
                 cssParWrap    = "cssTabWrap",
                 cssParams    = "cssTable",
                 cssParams    = "cssTable",
Zeile 30: Zeile 32:
                 msgDescMiss  = "solo",
                 msgDescMiss  = "solo",
                 tStylesTOCnum = "stylesTOCnum" },
                 tStylesTOCnum = "stylesTOCnum" },
--  classParams    = "classTable",
    classTable    = { "wikitable" },    -- classes for params table
--  classTable    = false,    -- class for params table
     debugmultilang = "C0C0C0",
     debugmultilang = "C0C0C0",
     loudly        = false,    -- show exported element, etc.
     loudly        = false,    -- show exported element, etc.
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 66: Zeile 68:
}
}
local Permit = {
local Permit = {
     builder = { after     = "block",
     builder = { after           = "block",
                 align     = "block",
                 align           = "block",
                 block     = "block",
                 block           = "block",
                 compressed = "block",
                 compressed     = "block",
                 dense     = "block",
                 dense           = "block",
                 grouped   = "inline",
                 grouped         = "inline",
                 half       = "inline",
                 half           = "inline",
                 indent     = "block",
                 indent         = "block",
                 inline     = "inline",
                 inline         = "inline",
                 last       = "block",
                 last           = "block",
                 lead       = "block",
                 lead           = "block",
                 newlines   = "*",
                 newlines       = "*",
                 spaced     = "inline" },
                 spaced         = "inline" },
     colors  = { tableheadbg = "B3B7FF",
     colors  = { tableheadbg = "B3B7FF",
                 required    = "EAF3FF",
                 required    = "EAF3FF",
Zeile 84: Zeile 86:
                 optional    = "EAECF0",
                 optional    = "EAECF0",
                 deprecated  = "FFCBCB" },
                 deprecated  = "FFCBCB" },
     params  = { aliases     = "table",
     params  = { aliases         = "table",
                 autovalue   = "string",
                 autovalue       = "string",
                 default     = "string table I18N nowiki",
                 default         = "string table I18N nowiki",
                 deprecated = "boolean string I18N",
                 deprecated     = "boolean string I18N",
                 description = "string table I18N",
                 description     = "string table I18N",
                 example     = "string table I18N nowiki",
                 example         = "string table I18N nowiki",
                 label       = "string table I18N",
                 label           = "string table I18N",
                 inherits   = "string",
                 inherits       = "string",
                 required   = "boolean",
                 required       = "boolean",
                 style       = "string table",
                 style           = "string table",
                 suggested   = "boolean",
                 suggested       = "boolean",
                 type       = "string" },
                suggestedvalues = "string table number",
                 type           = "string" },
     root    = { description = "string table I18N",
     root    = { description = "string table I18N",
                 format      = "string",
                 format      = "string",
Zeile 171: Zeile 174:
             TemplateData.extern[ sign ] = r
             TemplateData.extern[ sign ] = r
         elseif not allow then
         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
Zeile 183: Zeile 186:
     -- Returns slang, or not
     -- Returns slang, or not
     if type( Data.slang ) == "nil" then
     if type( Data.slang ) == "nil" then
         local Multilingual = Fetch( "Multilingual" )
         local Multilingual = Fetch( "Multilingual", true )
         if type( Multilingual.userLangCode ) == "function" then
         if Multilingual  and
          type( Multilingual.userLangCode ) == "function" then
             Data.slang = Multilingual.userLangCode()
             Data.slang = Multilingual.userLangCode()
         else
         else
             Data.slang = false
             Data.slang = mw.language.getContentLanguage():getCode()
                                                        :lower()
         end
         end
     end
     end
Zeile 209: Zeile 214:
                                   :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 221: Zeile 234:
             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 289: Zeile 302:
     --    adjust  -- string
     --    adjust  -- string
     -- Returns string, with adjusted text
     -- Returns string, with adjusted text
     local f = function ( a )
     local f   = function ( a )
                  return a:gsub( "%s*\n%s*", " " )
                    return a:gsub( "%s*\n%s*", " " )
                          :gsub( "%s%s+", " " )
                            :gsub( "%s%s+", " " )
              end
                end
     local r
     local tags = { { start = "<noexport>",
    if adjust:find( "<noexport>", 1, true ) then
                    stop  = "</noexport>" },
        local i    = 1
                  { start = "<exportonly>",
        local j, k = adjust:find( "<noexport>", i, true )
                    stop  = "</exportonly>",
        r = ""
                    l    = false }
        while j do
                }
            if j > 1 then
    local r = adjust
                r = r .. f( adjust:sub( i, j - 1 ) )
    local i, j, k, s, tag
             end
    for m = 1, 2 do
             i = k + 1
        tag = tags[ m ]
             j, k = adjust:find( "</noexport>", i, true )
        if r:find( tag.start, 1, true ) then
             if j then
            s    = r
                r   = r .. adjust:sub( i,  j - 1 )
             r    = ""
             i     = 1
            tag.l = true
             j, k = s:find( tag.start, i, true )
             while j do
                if j > 1 then
                    r = r .. f( s:sub( i,  j - 1 ) )
                end
                 i    = k + 1
                 i    = k + 1
                 j, k = adjust:find( "<noexport>", i, true )
                 j, k = s:find( tag.stop, i, true )
            else
                if j then
                Fault( "missing </noexport>" )
                    if m == 1 then
            end
                        r = r .. s:sub( i,  j - 1 )
        end    -- while j
                    end
        r = r .. adjust:sub( i )
                    i    = k + 1
     else
                    j, k = s:find( tag.start, i, true )
         r = f( adjust )
                else
                    Fault( "missing " .. tag.stop )
                end
            end    -- while j
            r = r .. s:sub( i )
        elseif m == 1 then
            r = f( r )
        end
    end -- for m
     if tags[ 2 ].l then
         r = r:gsub( "<exportonly>.*</exportonly>", "" )
     end
     end
     return r
     return r
end -- fair()
end -- fair()




Zeile 376: Zeile 405:
     local variants = { }
     local variants = { }
     local r1, r2
     local r1, r2
    Foreign()
     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 388: Zeile 416:
     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 651: Zeile 676:




local function feat()
local function feasible( about, at )
     -- Check and store parameter sequence
     -- Deal with suggestedvalues within parameter
     if Data.source then
    -- Parameter:
        local i = 0
    --    about  -- parameter details
        local s
    --              .suggestedvalues  -- table|string|number,
         for k, v in pairs( Data.tree.params ) do
    --                                    value and possibly description
            if i == 0 then
    --                                    .code  -- mandatory
                Data.order = { }
    --                                    .label  -- table|string
                 i = 1
    --                                    .icon  -- string
                 s = k
    --                                    .class  -- table|string
            else
    --                                    .css    -- table
                 i = 2
    --                                    .style  -- string
                 break -- for k, v
    --                                    .less  -- true: suppress code
            end
    --              .type
         end -- for k, v
    --    at    -- string, with parameter name
         if i > 1 then
    -- Returns
             local pointers = { }
    --    1: mw.html object
             local points  = { }
    --    2: sequence table with values, or nil
            for k, v in pairs( Data.tree.params ) do
     local p = about.suggestedvalues
                 i = facet( k, 1 )
    local s = type( p )
                if i then
    local e, r1, r2, v
                     table.insert( points, i )
    if s == "table" then
                     pointers[ i ] = k
         if #p > 0 then
                     i = facet( k, i )
            for i = 1, #p do
                     if i then
                e = p[ i ]
                         s = "Parameter '%s' detected twice"
                s = type( e )
                         Fault( string.format( s, k ) )
                if s == "table" then
                    if type( e.code ) == "string" then
                        s = mw.text.trim( e.code )
                        if s == "" then
                            e = nil
                        else
                            e.code = s
                        end
                    else
                        e = nil
                        s = string.format( "params.%s.%s[%d] %s",
                                          at,
                                          "suggestedvalues",
                                          i,
                                          "MISSING 'code:'" )
                    end
                elseif s == "string" then
                    s = mw.text.trim( e )
                    if s == "" then
                        e = nil
                        s = string.format( "params.%s.%s[%d] EMPTY",
                                          at, "suggestedvalues", i )
                        Fault( s )
                    else
                        e = { code = s }
                    end
                 elseif s == "number" then
                    e = { code = tostring( e ) }
                 else
                    s = string.format( "params.%s.%s[%d] INVALID",
                                      at, "suggestedvalues", i )
                    Fault( s )
                    e = false
                end
                 if e then
                    v = v  or  { }
                    table.insert( v, e )
                 end
            end -- for i
        else
            Fault( string.format( "params.%s.suggestedvalues %s",
                  at, "NOT AN ARRAY" ) )
        end
    elseif s == "string" then
         s = mw.text.trim( p )
         if s ~= "" then
             v = { }
             table.insert( v,
                          { code = s } )
        end
    elseif s == "number" then
        v = { }
        table.insert( v,
                      { code = tostring( p ) } )
    end
    if v then
        local d, less, story, swift, t, u
        r1 = mw.html.create( "ul" )
        r2 = { }
        for i = 1, #v do
            u = mw.html.create( "li" )
            e = v[ i ]
            table.insert( r2, e.code )
            story = false
            less  = ( e.less == true )
            if not less then
                swift = e.code
                 if e.support then
                    local scream, support
                    s = type( e.support )
                    if s == "string" then
                        support = e.support
                     elseif s == "table" then
                        support = faraway( e.support )
                     else
                        scream = "INVALID"
                    end
                     if support then
                        s = mw.text.trim( support )
                        if s == "" then
                            scream = "EMPTY"
                        elseif s:find( "[%[%]|%<%>]" ) then
                            scream = "BAD PAGE"
                        else
                            support = s
                        end
                    end
                     if scream then
                         s = string.format( "params.%s.%s[%d].support %s",
                                          at,
                                          "suggestedvalues",
                                          i,
                                          scream )
                         Fault( s )
                    else
                        swift = string.format( "[[:%s|%s]]",
                                              support, swift )
                    end
                end
                if about.type:sub( 1, 5 ) == "wiki-"  and
                  swift == e.code then
                    local rooms = { file = 6,
                                    temp = 10,
                                    user = 2 }
                    local ns = rooms[ about.type:sub( 6, 9 ) ]  or  0
                    t = mw.title.makeTitle( ns, swift )
                    if t and t.exists then
                        swift = string.format( "[[:%s|%s]]",
                                              t.prefixedText, swift )
                     end
                     end
                end
                u:node( mw.html.create( "code" )
                              :css( "white-space", "nowrap" )
                              :wikitext( swift ) )
            end
            if e.class then
                s = type( e.class )
                if s == "string" then
                    u:addClass( e.class )
                elseif s == "table" then
                    for k, s in pairs( e.class ) do
                        u:addClass( s )
                    end -- for k, s
                 else
                 else
                     s = "Parameter '%s' not detected"
                     s = string.format( "params.%s.%s[%d].class INVALID",
                     Fault( string.format( s, k ) )
                                      at, "suggestedvalues", i )
                     Fault( s )
                 end
                 end
             end -- for k, v
             end
             table.sort( points )
             if e.css then
             for i = 1, #points do
                if type( e.css ) == "table" then
                 table.insert( Data.order, pointers[ points[ i ] ] )
                    u:css( e.css )
             end -- i = 1, #points
                else
        elseif s then
                    s = string.format( "params.%s.%s[%d].css INVALID",
            table.insert( Data.order, s )
                                      at, "suggestedvalues", i )
        end
                    Fault( s )
    end
                end
end -- feat()
             end
 
            if e.style then
 
                if type( e.style ) == "string" then
 
                    u:cssText( e.style )
local function feature( access )
                 else
    -- Create table row for parameter, check and display violations
                    s = string.format( "params.%s.%s[%d].style INVALID",
    -- Parameter:
                                      at, "suggestedvalues", i )
    --    access  -- string, with name
                    Fault( s )
    -- Returns <tr>
                end
    local mode, s, status
             end
    local fine    = function ( a )
            if about.type == "wiki-file-name"  and  not e.icon then
                        s = mw.text.trim( a )
                e.icon = e.code
                        return a == s and
            end
                              a ~= "" and
            if e.label then
                              not a:find( "%|=\n" ) and
                s = type( e.label )
                              not a:find( "%s%s" )
                if s == "string" then
                    s = mw.text.trim( e.label )
                    if s == "" then
                        s = string.format( "params.%s.%s[%d].label %s",
                                          at,
                                          "suggestedvalues",
                                          i,
                                          "EMPTY" )
                        Fault( s )
                    else
                        story = s
                    end
                elseif s == "table" then
                    story = faraway( e.label )
                else
                    s = string.format( "params.%s.%s[%d].label INVALID",
                                      at, "suggestedvalues", i )
                    Fault( s )
                end
            end
            s = false
            if type( e.icon ) == "string" then
                t = mw.title.makeTitle( 6, e.icon )
                if t and t.file.exists then
                    local g = mw.html.create( "span" )
                    s = string.format( "[[%s|16px]]", t.prefixedText )
                    g:attr( "role", "presentation" )
                    :wikitext( s )
                    s = tostring( g )
                end
            end
            if not s  and  not less  and  e.label then
                s = mw.ustring.char( 0x2013 )
            end
            if s then
                d = mw.html.create( "span" )
                          :wikitext( s )
                if TemplateData.ltr then
                    if not less then
                        d:css( "margin-left", "0.5em" )
                    end
                    if story then
                        d:css( "margin-right", "0.5em" )
                    end
                else
                    if not less then
                        d:css( "margin-right", "0.5em" )
                    end
                    if story then
                        d:css( "margin-left", "0.5em" )
                     end
                     end
     local begin  = mw.html.create( "td" )
                end
    local code    = mw.html.create( "code" )
                u:node( d )
    local desc    = mw.html.create( "td" )
            end
    local legal  = true
            if story then
     local param  = Data.tree.params[ access ]
                u:wikitext( story )
     local ranking = { "required", "suggested", "optional", "deprecated" }
            end
    local r      = mw.html.create( "tr" )
            r1:newline()
    local sort, typed
              :node( u )
        end -- for i
    end
     if not r1 then
        Fault( string.format( "params.%s.suggestedvalues INVALID", at ) )
        r1 = mw.html.create( "code" )
                    :addClass( "error" )
                    :wikitext( "INVALID" )
     end
     return r1, r2
end -- feasible()


    for k, v in pairs( param ) do
        if v == "" then
            param[ k ] = false
        end
    end -- for k, v


    -- label
    sort = param.label or access
    if sort:match( "^%d+$" ) then
        begin:attr( "data-sort-value",
                    string.format( "%05d", tonumber( sort ) ) )
    end
    begin:css( "font-weight", "bold" )
        :wikitext( sort )


    -- name and aliases
local function feat()
    code:css( "font-size", "92%" )
     -- Check and store parameter sequence
        :css( "white-space", "nowrap" )
     if Data.source then
        :wikitext( access )
         local i = 0
     if not fine( access ) then
         local s
        code:addClass( "error" )
         for k, v in pairs( Data.tree.params ) do
        Fault( string.format( "Bad ID params.<code>%s</code>", access ) )
             if i == 0 then
        legal = false
                 Data.order = { }
        begin:attr( "data-sort-value",  " " .. sort )
                 i = 1
     end
                 s = k
    code = mw.html.create( "td" )
                  :node( code )
    if access:match( "^%d+$" ) then
         code:attr( "data-sort-value",
                  string.format( "%05d", tonumber( access ) ) )
    end
    if type( param.aliases ) == "table" then
         local lapsus
         for k, v in pairs( param.aliases ) do
            code:tag( "br" )
             if type( v ) == "string" then
                 if not fine( v ) then
                    lapsus = true
                    code:node( mw.html.create( "span" )
                                      :addClass( "error" )
                                      :css( "font-style", "italic" )
                                      :wikitext( "string" ) )
                 end
                 code:wikitext( s )
             else
             else
                 lapsus = true
                 i = 2
                 code:node( mw.html.create( "code" )
                 break -- for k, v
                                  :addClass( "error" )
                                  :wikitext( type( v ) ) )
             end
             end
         end -- for k, v
         end -- for k, v
         if lapsus then
         if i > 1 then
             s = string.format( "params.<code>%s</code>.aliases", access )
             local pointers = { }
            Fault( factory( "invalid-value" ):gsub( "$1", s ) )
            local points  = { }
            legal = false
            local given    = { }
        end
            for k, v in pairs( Data.tree.params ) do
    end
                i = facet( k, 1 )
 
                if type( v ) == "table" then
    -- description etc.
                    if type( v.label ) == "string" then
    s = fashioned( param )
                        s = mw.text.trim( v.label )
    if s then
                        if s == "" then
        desc:node( s )
                            s = k
    end
                        end
    if param.style then
                    else
        s = type( param.style )
                        s = k
        if s == "table" then
                    end
             desc:css( param.style )
                    if given[ s ] then
         elseif s == "string" then
                        if given[ s ] == 1 then
             desc:cssText( param.style )
                            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
                    table.insert( points, i )
                    pointers[ i ] = k
                    i = facet( k, i )
                    if i then
                        s = "Parameter '%s' detected twice"
                        Fault( string.format( s, k ) )
                    end
                else
                    s = "Parameter '%s' not detected"
                    Fault( string.format( s, k ) )
                end
            end -- for k, v
            table.sort( points )
             for i = 1, #points do
                table.insert( Data.order,  pointers[ points[ i ] ] )
            end -- i = 1, #points
         elseif s then
             table.insert( Data.order, s )
         end
         end
     end
     end
    if param.default or param.example or param.autovalue then
end -- feat()
        local details = { "default", "example", "autovalue" }
 
        local dl      = mw.html.create( "dl" )
 
        local dd, section, show
 
        for i = 1, #details do
local function feature( access )
            s   = details[ i ]
    -- Create table row for parameter, check and display violations
            show = param[ s ]
    -- Parameter:
            if show then
    --    access  -- string, with name
                dd      = mw.html.create( "dd" )
    -- Returns <tr>
                section = factory( "doc-param-" .. s )
    local mode, s, status
                if param.type == "boolean"   and
    local fine   = function ( a )
                  ( show == "0" or show == "1" ) then
                        s = mw.text.trim( a )
                    local boole = Permit.boole[ ( show == "1" ) ]
                        return a == s and
                    if boole.lead == true then
                              a ~= "" and
                        dd:node( mw.html.create( "code" )
                              not a:find( "%|=\n" ) and
                                        :wikitext( show ) )
                              not a:find( "%s%s" )
                          :wikitext( " " )
                     end
                     end
                    if type( boole.show ) == "string" then
    local begin  = mw.html.create( "td" )
                        local v = mw.html.create( "span" )
    local code    = mw.html.create( "code" )
                                        :wikitext( boole.show )
    local desc    = mw.html.create( "td" )
                        if boole.css then
    local eager  = mw.html.create( "td" )
                            v:css( boole.css )
    local legal  = true
                        end
    local param  = Data.tree.params[ access ]
                        dd:node( v )
    local ranking = { "required", "suggested", "optional", "deprecated" }
                    end
    local r      = mw.html.create( "tr" )
                    if type( boole.suffix ) == "string" then
    local styles  = "mw-templatedata-doc-param-"
                        dd:wikitext( boole.suffix )
    local sort, typed
                    end
 
                    if boole.lead == false then
    for k, v in pairs( param ) do
                        dd:wikitext( " " )
        if v == "" then
                          :node( mw.html.create( "code" )
            param[ k ] = false
                                        :wikitext( show ) )
        end
                    end
    end -- for k, v
                else
 
                    dd:wikitext( show )
    -- label
                end
    sort = param.label or access
                dl:node( mw.html.create( "dt" )
    if sort:match( "^%d+$" ) then
                                :wikitext( section ) )
        begin:attr( "data-sort-value",
                  :node( dd )
                    string.format( "%05d", tonumber( sort ) ) )
            end
        end -- i = 1, #details
        desc:node( dl )
     end
     end
    begin:css( "font-weight", "bold" )
        :wikitext( sort )


     -- type
     -- name and aliases
     if param.type then
    code:css( "font-size", "92%" )
         s     = Permit.types[ param.type ]
        :css( "white-space", "nowrap" )
        typed = mw.html.create( "td" )
        :wikitext( access )
        if s then
     if not fine( access ) then
            if s == "string" then
         code:addClass( "error" )
                Data.params[ access ].type = s
        Fault( string.format( "Bad ID params.<code>%s</code>", access ) )
                typed:wikitext( factory( "doc-param-type-" .. s ) )
        legal = false
                    :tag( "br" )
        begin:attr( "data-sort-value",  " " .. sort )
                 typed:node( mw.html.create( "span" )
    end
                                  :addClass( "error" )
    code = mw.html.create( "td" )
                                  :wikitext( param.type ) )
                  :addClass( styles .. "name" )
                 Data.lasting = true
                  :node( code )
            else
    if access:match( "^%d+$" ) then
                local support = Config[ "support4" .. param.type ]
        code:attr( "data-sort-value",
                s = factory( "doc-param-type-" .. param.type )
                  string.format( "%05d", tonumber( access ) ) )
                if support then
    end
                     s = string.format( "[[%s|%s]]", support, s )
    if type( param.aliases ) == "table" then
        local lapsus, syn
        for k, v in pairs( param.aliases ) do
            code:tag( "br" )
            if type( v ) == "string" then
                 if not fine( v ) then
                    lapsus = true
                    code:node( mw.html.create( "span" )
                                      :addClass( "error" )
                                      :css( "font-style", "italic" )
                                      :wikitext( "string" ) )
                        :wikitext( s )
                 else
                    syn = mw.html.create( "span" )
                                :addClass( styles .. "alias" )
                                :css( "white-space", "nowrap" )
                                :wikitext( s )
                     code:node( syn )
                 end
                 end
                 typed:wikitext( s )
            else
                 lapsus = true
                code:node( mw.html.create( "code" )
                                  :addClass( "error" )
                                  :wikitext( type( v ) ) )
             end
             end
         else
         end -- for k, v
            Data.params[ access ].type = "unknown"
        if lapsus then
            typed:addClass( "error" )
             s = string.format( "params.<code>%s</code>.aliases", access )
                :wikitext( "INVALID" )
             s = string.format( "params.<code>%s</code>.type", access )
             Fault(  factory( "invalid-value" ):gsub( "$1", s )  )
             Fault(  factory( "invalid-value" ):gsub( "$1", s )  )
             legal = false
             legal = false
         end
         end
    else
        typed = mw.html.create( "td" )
                  :wikitext( factory( "doc-param-type-unknown" ) )
     end
     end


     -- status
     -- description etc.
     if param.required then
     s = fashioned( param )
        mode = 1
    if s then
        if param.autovalue then
         desc:node( s )
            Fault( string.format( "autovalued <code>%s</code> required",
    end
                                  access ) )
     if param.style then
            legal = false
         s = type( param.style )
        end
        if s == "table" then
        if param.default then
            desc:css( param.style )
            Fault( string.format( "Defaulted <code>%s</code> required",
         elseif s == "string" then
                                  access ) )
             desc:cssText( param.style )
            legal = false
         end
        if param.deprecated then
            Fault( string.format( "Required deprecated <code>%s</code>",
                                  access ) )
            legal = false
        end
     elseif param.deprecated then
         mode = 4
    elseif param.suggested then
        mode = 2
    else
        mode = 3
    end
    status = ranking[ mode ]
    ranking = factory( "doc-param-status-" .. status )
    if mode == 1  or  mode == 4 then
        ranking = mw.html.create( "span" )
                        :css( "font-weight", "bold" )
                        :wikitext( ranking )
         if type( param.deprecated ) == "string" then
             ranking:tag( "br" )
            ranking:wikitext( param.deprecated )
         end
         end
    end
    if param.suggestedvalues or
      param.default or
      param.example or
      param.autovalue then
        local details = { "suggestedvalues",
                          "default",
                          "example",
                          "autovalue" }
        local dl      = mw.html.create( "dl" )
        local dd, section, show
        for i = 1, #details do
            s    = details[ i ]
            show = param[ s ]
            if show then
                dd      = mw.html.create( "dd" )
                section = factory( "doc-param-" .. s )
                if param.type == "boolean"  and
                  ( show == "0" or show == "1" ) then
                    local boole = Permit.boole[ ( show == "1" ) ]
                    if boole.lead == true then
                        dd:node( mw.html.create( "code" )
                                        :wikitext( show ) )
                          :wikitext( " " )
                    end
                    if type( boole.show ) == "string" then
                        local v = mw.html.create( "span" )
                                        :attr( "aria-hidden", "true" )
                                        :wikitext( boole.show )
                        if boole.css then
                            v:css( boole.css )
                        end
                        dd:node( v )
                    end
                    if type( boole.suffix ) == "string" then
                        dd:wikitext( boole.suffix )
                    end
                    if boole.lead == false then
                        dd:wikitext( " " )
                          :node( mw.html.create( "code" )
                                        :wikitext( show ) )
                    end
                elseif s == "suggestedvalues" then
                    local html, values = feasible( param, access )
                    dd:newline()
                      :node( html )
                    Data.params[ access ].suggestedvalues = values
                else
                    dd:wikitext( show )
                end
                dl:node( mw.html.create( "dt" )
                                :wikitext( section ) )
                  :node( dd )
            end
        end -- i = 1, #details
        desc:node( dl )
     end
     end


     -- <tr>
     -- type
     r:attr( "id",  "templatedata:" .. mw.uri.anchorEncode( access ) )
     if type( param.type ) == "string" then
    :css( Permit.css[ status ] )
        param.type = mw.text.trim( param.type )
    :node( begin )
        if param.type == "" then
    :node( code )
            param.type = false
    :node( desc )
         end
    :node( typed )
    :node( mw.html.create( "td" )
                  :attr( "data-sort-value", tostring( mode ) )
                  :node( ranking ) )
    :newline()
    if not legal then
         r:css( "border", "#FF0000 3px solid" )
     end
     end
     return r
     if param.type then
end -- feature()
        s     = Permit.types[ param.type ]
 
         typed = mw.html.create( "td" )
 
                  :addClass( styles .. "type" )
 
         if s then
local function features()
            if s == "string" then
     -- Create <table> for parameters
                Data.params[ access ].type = s
    -- Returns <table>, or nil
                typed:wikitext( factory( "doc-param-type-" .. s ) )
    local r
                    :tag( "br" )
    if Data.tree and Data.tree.params then
                typed:node( mw.html.create( "span" )
         local tbl = mw.html.create( "table" )
                                  :addClass( "error" )
                          :addClass( "wikitable" )
                                  :wikitext( param.type ) )
         local tr  = mw.html.create( "tr" )
                Data.lasting = true
        feat()
             else
        if Data.order  and  #Data.order > 1 then
                local support = Config[ "support4" .. param.type ]
            tbl:addClass( "sortable" )
                 s = factory( "doc-param-type-" .. param.type )
        end
                if support then
--      if Config.classTable then
                    s = string.format( "[[%s|%s]]", support, s )
--          tbl:addClass( Config.classTable )
                 end
--      end
                 typed:wikitext( s )
        if Config.cssTable then
             if type( Config.cssTable ) == "table" then
                 tbl:css( Config.cssTable )
            elseif type( Config.cssTable ) == "string" then
                 -- deprecated
                 tbl:cssText( Config.cssTable )
             end
             end
        else
            Data.params[ access ].type = "unknown"
            typed:addClass( "error" )
                :wikitext( "INVALID" )
            s = string.format( "params.<code>%s</code>.type", access )
            Fault(  factory( "invalid-value" ):gsub( "$1", s )  )
            legal = false
         end
         end
         tr:node( mw.html.create( "th" )
    else
                        :attr( "colspan", "2" )
         typed = mw.html.create( "td" )
                        :css( Permit.css.tablehead )
                  :wikitext( factory( "doc-param-type-unknown" ) )
                        :wikitext( factory( "doc-param-name" ) ) )
        Data.params[ access ].type = "unknown"
          :node( mw.html.create( "th" )
        if param.default then
                        :css( Permit.css.tablehead )
            Data.params[ access ].default = nil
                        :wikitext( factory( "doc-param-desc" ) ) )
            Fault( "Default value requires <code>type</code>" )
          :node( mw.html.create( "th" )
            legal = false
                        :css( Permit.css.tablehead )
        end
                        :wikitext( factory( "doc-param-type" ) ) )
    end
          :node( mw.html.create( "th" )
    -- status
                        :css( Permit.css.tablehead )
    if param.required then
                        :wikitext( factory( "doc-param-status" ) ) )
         mode = 1
         tbl:newline()
         if param.autovalue then
--         :node( mw.html.create( "thead" )
            Fault( string.format( "autovalued <code>%s</code> required",
                        :node( tr )
                                  access ) )
--              )
            legal = false
          :newline()
        end
         if Data.order then
         if param.default then
             local leave, s
             Fault( string.format( "Defaulted <code>%s</code> required",
            for i = 1, #Data.order do
                                  access ) )
                s = Data.order[ i ]
            legal = false
                if s:sub( 1, 1 ) == "=" then
        end
                    leave = true
        if param.deprecated then
                    tbl:node( fatten( s ) )
            Fault( string.format( "Required deprecated <code>%s</code>",
                    Data.order[ i ] = false
                                  access ) )
                elseif s:match( "[=|]" ) then
            legal = false
                    Fault( string.format( "Bad param <code>%s</code>",
        end
                                          s ) )
    elseif param.deprecated then
                else
        mode = 4
                    tbl:node( feature( s ) )
    elseif param.suggested then
                end
        mode = 2
            end -- for i = 1, #Data.order
    else
            if leave then
        mode = 3
                for i = #Data.order, 1, -1 do
    end
                    if not Data.order[ i ] then
    status = ranking[ mode ]
                        table.remove( Data.order, i )
    ranking = factory( "doc-param-status-" .. status )
                    end
    if mode == 1  or  mode == 4 then
                end -- for i = #Data.order, 1, -1
        ranking = mw.html.create( "span" )
             end
                        :css( "font-weight", "bold" )
             Data.tag.paramOrder = Data.order
                        :wikitext( ranking )
        if type( param.deprecated ) == "string" then
             ranking:tag( "br" )
             ranking:wikitext( param.deprecated )
         end
         end
         if Config.cssTabWrap or Data.scroll then
         if param.suggested  and  mode == 4 then
            r = mw.html.create( "div" )
             s = string.format( "Suggesting deprecated <code>%s</code>",
            if type( Config.cssTabWrap ) == "table" then
                              access )
                r:css( Config.cssTabWrap )
             Fault( s )
             elseif type( Config.cssTabWrap ) == "string" then
             legal = false
                -- deprecated
                r:cssText( Config.cssTabWrap )
            end
            if Data.scroll then
                r:css( "height",   Data.scroll )
                :css( "overflow", "auto" )
             end
            r:node( tbl )
        else
             r = tbl
         end
         end
    end
    eager:attr( "data-sort-value", tostring( mode ) )
                :node( ranking )
                :addClass( string.format( "%sstatus-%s",
                                          styles, status ) )
    -- <tr>
    r:attr( "id",  "templatedata:" .. mw.uri.anchorEncode( access ) )
    :css( Permit.css[ status ] )
    :addClass( styles .. status )
    :node( begin )
    :node( code )
    :node( desc )
    :node( typed )
    :node( eager )
    :newline()
    if not legal then
        r:css( "border", "#FF0000 3px solid" )
     end
     end
     return r
     return r
end -- features()
end -- feature()






local function finalize( advance )
local function features()
     -- Wrap presentation into frame
    -- Create <table> for parameters
     -- Parameter:
    -- Returns <table>, or nil
     --    advance  -- true, for nice
    local r
     -- Returns string
    if Data.tree and Data.tree.params then
     local r, lapsus
        local tbl = mw.html.create( "table" )
     if Data.div then
        local tr  = mw.html.create( "tr" )
         r = tostring( Data.div )
        feat()
     elseif Data.strip then
        if Data.order  and  #Data.order > 1 then
         r = Data.strip
            tbl:addClass( "sortable" )
     else
        end
         lapsus = true
        if type( Config.classTable ) == "table" then
         r      = ""
            for k, v in pairs( Config.classTable ) do
     end
                tbl:addClass( v )
     r = r .. failures()
            end -- for k, v
     if Data.source then
        end
         local live = ( advance or lapsus )
        if type( Config.cssTable ) == "table" then
         if not live then
            tbl:css( Config.cssTable )
             live = TemplateData.frame:preprocess( "{{REVISIONID}}" )
        end
             live = ( live == "" )
        tr:node( mw.html.create( "th" )
                        :attr( "colspan", "2" )
                        :css( Permit.css.tablehead )
                        :wikitext( factory( "doc-param-name" ) ) )
          :node( mw.html.create( "th" )
                        :css( Permit.css.tablehead )
                        :wikitext( factory( "doc-param-desc" ) ) )
          :node( mw.html.create( "th" )
                        :css( Permit.css.tablehead )
                        :wikitext( factory( "doc-param-type" ) ) )
          :node( mw.html.create( "th" )
                        :css( Permit.css.tablehead )
                        :wikitext( factory( "doc-param-status" ) ) )
        tbl:newline()
--        :node( mw.html.create( "thead" )
                        :node( tr )
--              )
          :newline()
        if Data.order then
            local leave, s
            for i = 1, #Data.order do
                s = Data.order[ i ]
                if s:sub( 1, 1 ) == "=" then
                    leave = true
                    tbl:node( fatten( s ) )
                    Data.order[ i ] = false
                elseif s:match( "[=|]" ) then
                    Fault( string.format( "Bad param <code>%s</code>",
                                          s ) )
                else
                    tbl:node( feature( s ) )
                end
            end -- for i = 1, #Data.order
            if leave then
                for i = #Data.order, 1, -1 do
                    if not Data.order[ i ] then
                        table.remove( Data.order, i )
                    end
                end -- for i = #Data.order, 1, -1
            end
            Data.tag.paramOrder = Data.order
        end
        if Config.cssTabWrap or Data.scroll then
            r = mw.html.create( "div" )
            if type( Config.cssTabWrap ) == "table" then
                r:css( Config.cssTabWrap )
            elseif type( Config.cssTabWrap ) == "string" then
                -- deprecated
                r:cssText( Config.cssTabWrap )
            end
            if Data.scroll then
                r:css( "height",  Data.scroll )
                :css( "overflow", "auto" )
            end
            r:node( tbl )
        else
            r = tbl
        end
    end
    return r
end -- features()
 
 
 
local function fellow( any, assigned, at )
    -- Check sets[] parameter and issue error message, if necessary
    -- Parameter:
    --    any      -- should be number
    --    assigned  -- parameter name
    --    at        -- number, of set
    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 )
     elseif Data.strip then
         r = Data.strip
     else
         lapsus = true
         r      = ""
     end
     r = r .. failures()
     if Data.source then
         local live = ( advance or lapsus )
         if not live then
             live = TemplateData.frame:preprocess( "{{REVISIONID}}" )
             live = ( live == "" )
        end
        if live then
            r = r .. fancy( advance, lapsus )
        end
    end
    return r
end -- finalize()
 
 
 
local function find()
    -- Find JSON data within page source (title)
    -- Returns string, or nil
    local s = Data.title:getContent()
    local i, j = s:find( "<templatedata>", 1, true )
    local r
    if i then
        local k = s:find( "</templatedata>", j, true )
        if k then
          r = mw.text.trim( s:sub( j + 1,  k - 1 ) )
        end
    end
    return r
end -- find()
 
 
 
local function flat( adjust )
    -- Remove formatting from text string for VE
    -- Parameter:
    --    arglist  -- string, to be stripped, or nil
    -- Returns string, or nil
    local r
    if adjust then
        r = adjust:gsub( "\n", " " )
        if r:find( "<noexport>", 1, true ) then
            r = r:gsub( "<noexport>.*</noexport>", "" )
        end
        if r:find( "<exportonly>", 1, true ) then
            r = r:gsub( "</?exportonly>", "" )
        end
        if r:find( "''", 1, true ) then
            r = r:gsub( "'''", "" ):gsub( "''", "" )
        end
        if r:find( "<", 1, true ) then
            local Text = Fetch( "Text" )
            r = Text.getPlain( r:gsub( "<br */?>", "\r\n" ) )
        end
        if r:find( "[", 1, true ) then
            local WLink = Fetch( "WLink" )
            if WLink.isBracketedURL( r ) then
                r = r:gsub( "%[([hf]tt?ps?://%S+) [^%]]+%]", "%1" )
            end
            r = WLink.getPlain( r )
         end
         end
         if live then
         if r:find( "&", 1, true ) then
             r = r .. fancy( advance, lapsus )
             r = mw.text.decode( r )
            if r:find( "&shy;", 1, true ) then
                r = r:gsub( "&shy;", "" )
            end
         end
         end
     end
     end
     return r
     return r
end -- finalize()
end -- flat()






local function find()
local function flush()
     -- Find JSON data within page source (title)
     -- JSON encode narrowed input; obey unnamed (numerical) parameters
     -- Returns string, or nil
     -- Returns <templatedata> JSON string
    local s = Data.title:getContent()
    local i, j = s:find( "<templatedata>", 1, true )
     local r
     local r
     if i then
     if Data.tag then
         local k = s:find( "</templatedata>", j, true )
         r = mw.text.jsonEncode( Data.tag ):gsub( "%}$", "," )
         if k then
    else
          r = mw.text.trim( s:sub( j + 1,  k - 1 ) )
         r = "{"
         end
    end
    r = r .. "\n\"params\":{"
    if Data.order then
        local sep = ""
        local s
        for i = 1, #Data.order do
            s  = Data.order[ i ]
            r   = string.format( "%s%s\n%s:%s",
                                r,
                                sep,
                                mw.text.jsonEncode( s ),
                                mw.text.jsonEncode( Data.params[ s ] ) )
            sep = ",\n"
         end -- for i = 1, #Data.order
     end
     end
    r = r .. "\n}\n}"
     return r
     return r
end -- find()
end -- flush()






local function flat( adjust )
local function focus( access )
     -- Remove formatting from text string
     -- Check components; focus multilingual description, build trees
     -- Parameter:
     -- Parameter:
     --    arglist -- string, to be stripped, or nil
     --    access -- string, name of parameter, nil for root
    -- Returns string, or nil
     local f = function ( a, at )
     local r
                    local r
    if adjust then
                    if at then
        r = adjust:gsub( "\n", " " )
                        r = string.format( "<code>params.%s</code>", at )
        if r:find( "<noexport>", 1, true ) then
                    else
            r = r:gsub( "<noexport>(.*)</noexport>", "" )
                        r = "''root''"
        end
                    end
        if r:find( "''", 1, true ) then
                    if a then
            r = r:gsub( "'''", "" ):gsub( "''", "" )
                        r = string.format( "%s<code>.%s</code>", r, a )
        end
                    end
        if r:find( "<", 1, true ) then
                    return r
            local Text = Fetch( "Text" )
                end
            r = Text.getPlain( r:gsub( "<br */?>", "\r\n" ) )
    local parent
         end
    if access then
        if r:find( "[", 1, true ) then
        parent = Data.got.params[ access ]
             local WLink = Fetch( "WLink" )
    else
             if WLink.isBracketedURL( r ) then
         parent = Data.got
                 r = r:gsub( "%[([hf]tt?ps?://%S+) [^%]]+%]", "%1" )
    end
    if type( parent ) == "table" then
        local elem, got, permit, s, scope, slot, tag, target
        if access then
             permit = Permit.params
             if type( access ) == "number" then
                 slot = tostring( access )
            else
                slot = access
             end
             end
             r = WLink.getPlain( r )
        else
             permit = Permit.root
         end
         end
         if r:find( "&", 1, true ) then
         for k, v in pairs( parent ) do
            r = mw.text.decode( r )
            scope = permit[ k ]
        end
            if scope then
    end
                s = type( v )
    return r
                if s == "string" and  k ~= "format" then
end -- flat()
                    v = mw.text.trim( v )
 
                end
 
                if scope:find( s, 1, true ) then
 
                    if scope:find( "I18N", 1, true ) then
local function flush()
                        if s == "string" then
    -- JSON encode narrowed input; obey unnamed (numerical) parameters
                            elem = fair( v )
    -- Returns <templatedata> JSON string
                        elseif s == "table" then
    local r
                            local translated
    if Data.tag then
                            v, translated = faraway( v )
        r = mw.text.jsonEncode( Data.tag ):gsub( "%}$", "," )
                            if v then
    else
                                if translated  and
        r = "{"
                                  k == "description" then
    end
                                    elem = { [ 1 ] = fair( v ),
    r = r .. "\n\"params\":{"
                                            [ 2 ] = translated }
    if Data.order then
                                else
        local sep = ""
                                    elem = fair( v )
        local s
                                end
        for i = 1, #Data.order do
                            else
            s  = Data.order[ i ]
                                elem = false
            r  = string.format( "%s%s\n%s:%s",
                            end
                                r,
                        end
                                sep,
                        if type( v ) == "string" then
                                mw.text.jsonEncode( s ),
                            if k == "deprecated" then
                                mw.text.jsonEncode( Data.params[ s ] ) )
                                if v == "1" then
            sep = ",\n"
                                    v = true
        end -- for i = 1, #Data.order
                                elseif v == "0" then
    end
                                    v = false
    r = r .. "\n}\n}"
                                end
    return r
                                elem = v
end -- flush()
                            elseif scope:find( "nowiki", 1, true ) then
 
                                elem = mw.text.nowiki( v )
 
                                elem = elem:gsub( "&#13;\n", "<br>" )
 
                                v    = v:gsub( string.char( 13 ),  "" )
local function focus( access )
                            else
    -- Check components; focus multilingual description, build trees
                                v = flat( v )
    -- Parameter:
                            end
    --    access  -- string, name of parameter, nil for root
                        elseif s == "boolean" then
    local f = function ( a, at )
                            if scope:find( "boolean", 1, true ) then
                    local r
                                elem = v
                    if at then
                            else
                        r = string.format( "<code>params.%s</code>", at )
                                s = "Type <code>boolean</code> bad for "
                                    .. f( k, slot )
                                Fault( s )
                            end
                        end
                     else
                     else
                         r = "''root''"
                         if k == "params" and  not access then
                    end
                            v    = nil
                    if a then
                            elem = nil
                         r = string.format( "%s<code>.%s</code>", r, a )
                         elseif k == "format" and  not access then
                    end
                            elem = mw.text.decode( v )
                    return r
                            v    = nil
                end
                        elseif k == "inherits" then
    local parent
                            elem = v
    if access then
                            if not Data.heirs then
        parent = Data.got.params[ access ]
                                Data.heirs = { }
    else
                            end
        parent = Data.got
                            Data.heirs[ slot ] = v
    end
                            v                  = nil
    if type( parent ) == "table" then
                        elseif k == "style" then
        local elem, got, permit, s, scope, slot, tag, target
                            elem = v
        if access then
                            v    = nil
            permit = Permit.params
                        elseif s == "string" then
            if type( access ) == "number" then
                            v   = mw.text.nowiki( v )
                slot = tostring( access )
                            elem = v
            else
                        else
                slot = access
                            elem = v
            end
                        end
        else
                    end
            permit = Permit.root
                     if type( elem ) ~= "nil" then
        end
                         if not target then
        for k, v in pairs( parent ) do
                             if access then
            scope = permit[ k ]
                                 if not Data.tree.params then
            if scope then
                                     Data.tree.params = { }
                s = type( v )
                if s == "string"  and  k ~= "format" then
                    v = mw.text.trim( v )
                end
                if scope:find( s, 1, true ) then
                     if scope:find( "I18N", 1, true ) then
                        if s == "string" then
                            elem = fair( v )
                         elseif s == "table" then
                            local translated
                            v, translated = faraway( v )
                             if v then
                                 if translated  and
                                  k == "description" then
                                     elem = { [ 1 ] = fair( v ),
                                            [ 2 ] = translated }
                                else
                                    elem = fair( v )
                                 end
                                 end
                                Data.tree.params[ slot ] = { }
                                target = Data.tree.params[ slot ]
                             else
                             else
                                 elem = false
                                 Data.tree = { }
                                target    = Data.tree
                             end
                             end
                         end
                         end
                         if type( v ) == "string" then
                         target[ k ] = elem
                             if k == "deprecated" then
                        elem        = false
                                if v == "1" then
                    end
                                     v = true
                    if type( v ) ~= "nil" then
                                 elseif v == "0" then
                        if not tag then
                                     v = false
                             if access then
                                if type( v ) == "string" and
                                  v.sub( 1, 1 ) == "=" then
                                     v = nil
                                 else
                                    if not Data.params then
                                        Data.params = { }
                                    end
                                    Data.params[ slot ] = { }
                                     tag = Data.params[ slot ]
                                 end
                                 end
                                elem = v
                            elseif scope:find( "nowiki", 1, true ) then
                                elem = mw.text.nowiki( v )
                                elem = elem:gsub( "&#13;\n", "<br>" )
                                v    = v:gsub( string.char( 13 ),  "" )
                             else
                             else
                                 v = flat( v )
                                 Data.tag = { }
                            end
                                 tag      = Data.tag
                        elseif s == "boolean" then
                            if scope:find( "boolean", 1, true ) then
                                elem = v
                            else
                                 s = "Type <code>boolean</code> bad for "
                                    .. f( k, slot )
                                Fault( s )
                             end
                             end
                         end
                         end
                    else
                         if type( v ) ~= "nil"  and
                         if k == "params"  and  not access then
                          k ~= "suggestedvalues" then
                            v    = nil
                             tag[ k ] = v
                            elem = nil
                         end
                        elseif k == "format"  and not access then
                    end
                            elem = mw.text.decode( v )
                else
                            v    = nil
                    s = string.format( "Type <code>%s</code> bad for %s",
                        elseif k == "inherits" then
                                      scope,  f( k, slot ) )
                             elem = v
                    Fault( s )
                            if not Data.heirs then
                end
                                Data.heirs = { }
            else
                            end
                Fault( "Unknown component " .. f( k, slot ) )
                            Data.heirs[ slot ] = v
            end
                            v                  = nil
        end -- for k, v
                         elseif k == "style" then
        if not access  and Data.got.sets then
                            elem = v
            fellows()
                            v    = nil
        end
                        elseif s == "string" then
    else
                            v    = mw.text.nowiki( v )
        Fault( f() .. " needs to be of <code>object</code> type" )
                            elem = v
    end
                        else
end -- focus()
                            elem = v
 
                        end
 
                    end
 
                    if type( elem ) ~= "nil" then
local function format()
                        if not target then
    -- Build formatted element
                            if access then
    -- Returns <inline>
                                if not Data.tree.params then
    local source = Data.tree.format:lower()
                                    Data.tree.params = { }
    local r, s
                                end
    if source == "inlineor  source == "block" then
                                Data.tree.params[ slot ] = { }
        r = mw.html.create( "i" )
                                target = Data.tree.params[ slot ]
                  :wikitext( source )
                            else
    else
                                Data.tree = { }
        local code
                                target    = Data.tree
        if source:find( "|", 1, true ) then
                            end
            local scan = "^[\n ]*%{%{[\n _]*|[\n _]*=[\n _]*%}%}[\n ]*$"
                        end
            if source:match( scan ) then
                        target[ k ] = elem
                code = source:gsub( "\n", "N" )
                        elem        = false
            else
                    end
                s = mw.text.nowiki( source ):gsub( "\n", "&#92;n" )
                    if type( v ) ~= "nil" then
                 s = tostring( mw.html.create( "code" )
                        if not tag then
                                    :wikitext( s ) )
                            if access then
                 Fault( "Invalid format " .. s )
                                if type( v ) == "stringand
                source = false
                                  v.sub( 1, 1 ) == "=" then
                                    v = nil
                                else
                                    if not Data.params then
                                        Data.params = { }
                                    end
                                    Data.params[ slot ] = { }
                                    tag = Data.params[ slot ]
                                end
                            else
                                Data.tag = { }
                                tag      = Data.tag
                            end
                        end
                        if type( v ) ~= "nil" then
                            tag[ k ] = v
                        end
                    end
                 else
                    s = string.format( "Type <code>%s</code> bad for %s",
                                      scope,  f( k, slot ) )
                    Fault( s )
                end
            else
                 Fault( "Unknown component " .. f( k, slot ) )
             end
             end
        end -- for k, v
         else
    else
             local words = mw.text.split( source, "%s+" )
        Fault( f() .. " needs to be of <code>object</code> type" )
             local show, start, support, unknown
    end
             for i = 1, #words do
end -- focus()
                 s = words[ i ]
 
                 if i == 1 then
 
 
local function format()
    -- Build formatted element
    -- Returns <inline>
    local source = Data.tree.format:lower()
    local r, s
    if source == "inline"  or  source == "block" then
        r = mw.html.create( "i" )
                  :wikitext( source )
    else
        local code
        if source:find( "|", 1, true ) then
            local scan = "^[\n ]*%{%{[\n _]*|[\n _]*=[\n _]*%}%}[\n ]*$"
            if source:match( scan ) then
                code = source:gsub( "\n", "N" )
            else
                s = mw.text.nowiki( source ):gsub( "\n", "&#92;n" )
                s = tostring( mw.html.create( "code" )
                                    :wikitext( s ) )
                Fault( "Invalid format " .. s )
                source = false
            end
         else
             local words = mw.text.split( source, "%s+" )
             local show, start, support, unknown
             for i = 1, #words do
                 s = words[ i ]
                 if i == 1 then
                     start = s
                     start = s
                 end
                 end
Zeile 1.405: Zeile 1.825:
                         end
                         end
                         if n > 1 then
                         if n > 1 then
                             spaced = string.rep( "_", n ) .. " "
                             spaced = string.rep( "_", n - 1 ) .. " "
                         end
                         end
                         show = show .. s
                         show = show .. s
Zeile 1.452: Zeile 1.872:
         end
         end
     end
     end
     if source then
     if source and Data.tag then
         Data.tag.format = source
         Data.tag.format = source
     end
     end
Zeile 1.510: Zeile 1.930:
     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.551: Zeile 1.971:
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.615: Zeile 2.037:
         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.674: Zeile 2.101:




TemplateData.failsafe = function ( atleast )
Failsafe.failsafe = function ( atleast )
     -- Retrieve versioning and check for compliance
     -- Retrieve versioning and check for compliance
     -- Precondition:
     -- Precondition:
     --    atleast  -- 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 = atleast
    --              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.707: Zeile 2.155:
     end
     end
     return r
     return r
end -- TemplateData.failsafe()
end -- Failsafe.failsafe()




Zeile 1.747: Zeile 2.195:
         free()
         free()
         if JSONutil then
         if JSONutil then
             Data.got = JSONutil.fetch( Data.source,
            local Multilingual = Fetch( "Multilingual", true )
                                      true,
            local f
                                      Foreign() )
            if Multilingual then
                f = Multilingual.i18n
            end
             Data.got = JSONutil.fetch( Data.source, true, f )
         else
         else
             local lucky
             local lucky
Zeile 1.757: Zeile 2.208:
             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.785: Zeile 2.242:
     end
     end
     return r
     return r
end -- p.f()
end -- p.f


p.failsafe = function ( frame )
p.failsafe = function ( frame )
Zeile 1.802: Zeile 2.259:
         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 ()