Modul:TemplatePar: Unterschied zwischen den Versionen

Zur Navigation springen Zur Suche springen
7.112 Bytes hinzugefügt ,  5. August 2018
c/p aus https://de.wikipedia.beta.wmflabs.org/w/index.php?title=Modul:TemplatePar&action=edit&oldid=22559 (Spezial:PermaLink/179745316#1× C&P Modul mit 700.000 Einbindungen)
K (21 Versionen importiert: Lua)
(c/p aus https://de.wikipedia.beta.wmflabs.org/w/index.php?title=Modul:TemplatePar&action=edit&oldid=22559 (Spezial:PermaLink/179745316#1× C&P Modul mit 700.000 Einbindungen))
Zeile 1: Zeile 1:
--[=[ TemplatePar 2015-02-14
local TemplatePar = { serial = "2018-08-04",
                      suite  = "TemplatePar",
                      item  = 15393417,
                      extern = { },
                      frame  = false }
--[=[
Template parameter utility
Template parameter utility
* assert
* assert
Zeile 6: Zeile 11:
* countNotEmpty
* countNotEmpty
* downcase()
* downcase()
* duplicates
* match
* match
* valid
* valid
* verify()
* verify()
* TemplatePar()
* TemplatePar()
* failsafe()
]=]
]=]


Zeile 15: Zeile 22:


-- Module globals
-- Module globals
local TemplatePar = { }
local MessagePrefix = "lua-module-TemplatePar-"
local MessagePrefix = "lua-module-TemplatePar-"
local L10nDef = {}
local L10nDef = {}
Zeile 36: Zeile 42:
     unknown    = "Error in template * unknown parameter name",
     unknown    = "Error in template * unknown parameter name",
     unknownRule = "#invoke:TemplatePar unknown rule"
     unknownRule = "#invoke:TemplatePar unknown rule"
}
L10nDef.de  = {
    badPattern  = "#invoke:TemplatePar Syntaxfehler des pattern",
    dupOpt      = "#invoke:TemplatePar Optionsparameter wiederholt",
    dupRule    = "#invoke:TemplatePar Konflikt key/pattern",
    empty      = "Fehler bei Vorlage * Pflichtparameter ohne Wert",
    invalid    = "Fehler bei Vorlage * Parameter ungültig",
    invalidPar  = "#invoke:TemplatePar Ungültiger Parameter",
    minmax      = "#invoke:TemplatePar min > max",
    multiSpell  = "Fehler bei Vorlage * Mehrere Parameter-Schreibweisen",
    noMSGnoCAT  = "#invoke:TemplatePar weder Meldung noch Kategorie",
    noname      = "#invoke:TemplatePar Parameter nicht angegeben",
    notFound    = "Fehler bei Vorlage * Seite fehlt",
    tooLong    = "Fehler bei Vorlage * Parameter zu lang",
    tooShort    = "Fehler bei Vorlage * Parameter zu kurz",
    undefined  = "Fehler bei Vorlage * Pflichtparameter fehlt",
    unknown    = "Fehler bei Vorlage * Parametername unbekannt",
    unknownRule = "#invoke:TemplatePar Unbekannte Regel"
}
}
local Patterns = {
local Patterns = {
Zeile 90: Zeile 78:
     [ "pagename" ] = string.format( "^[^#<>%%[%%]|{}%c-%c%c]+$",
     [ "pagename" ] = string.format( "^[^#<>%%[%%]|{}%c-%c%c]+$",
                                     1, 31, 127 ),
                                     1, 31, 127 ),
    [ "ref" ]      = string.format( "%c'%c`UNIQ%s%sref%s%s%sQINU`%c'%c",
                                    127, 34, "%-", "%-", "%-", "%d+",
                                    "%-", 34, 127 ),
     [ "+" ]        = "%S"
     [ "+" ]        = "%S"
}
}
Zeile 137: Zeile 128:
     --    Return error keyword, or false
     --    Return error keyword, or false
     -- Uses:
     -- Uses:
    --    >< TemplatePar.extern.FileMedia
     --    Module:FileMedia
     --    Module:FileMedia
     --    FileMedia.isType()
     --    FileMedia.isType()
     local r
     local r
     if attempt and attempt ~= "" then
     if attempt and attempt ~= "" then
         local lucky, FileMedia = pcall( require, "Module:FileMedia" )
         local FileMedia
        if TemplatePar.extern.FileMedia then
            FileMedia = TemplatePar.extern.FileMedia
        else
            local lucky
            lucky, FileMedia = pcall( require, "Module:FileMedia" )
            if type( FileMedia ) == "table" then
                FileMedia                    = FileMedia.FileMedia()
                TemplatePar.extern.FileMedia = FileMedia
            end
        end
         if type( FileMedia ) == "table" then
         if type( FileMedia ) == "table" then
            FileMedia = FileMedia.FileMedia()
             local s, live = accept:match( "^([a-z]+)(:?)%+?$" )
             local s, live = accept:match( "^([a-z]+)(:?)%+?$" )
             if live then
             if live then
Zeile 190: Zeile 191:
         local l10n = L10nDef[ c ]
         local l10n = L10nDef[ c ]
         if not l10n then
         if not l10n then
             l10n = L10nDef[ "en" ]
             local lucky
            lucky, l10n = pcall( mw.loadData,
                                string.format( "Module:%s/%s",
                                                TemplatePar.suite, c ) )
            if type( l10n ) == "table" then
                L10nDef[ c ] = l10n
            end
        end
        if type( l10n ) ~= "table" then
            l10n = L10nDef.en
         end
         end
         r = l10n[ say ]
         r = l10n[ say ]
        if not r then
            r = L10nDef.en[ say ]
        end
     else
     else
         m:inLanguage( c )
         m:inLanguage( c )
Zeile 202: Zeile 215:
     return r
     return r
end -- factory()
end -- factory()
local function failsafe( story, scan )
    -- Test for match (possibly user-defined with syntax error)
    -- Precondition:
    --    story  -- string; parameter value
    --    scan  -- string; pattern
    -- Postcondition:
    --    Return nil, if not matching, else non-nil
    -- Uses:
    --    mw.ustring.match()
    return  mw.ustring.match( story, scan )
end -- failsafe()




Zeile 243: Zeile 242:
     return r
     return r
end -- failure()
end -- failure()
local function fair( story, scan )
    -- Test for match (possibly user-defined with syntax error)
    -- Precondition:
    --    story  -- string; parameter value
    --    scan  -- string; pattern
    -- Postcondition:
    --    Return nil, if not matching, else non-nil
    -- Uses:
    --    mw.ustring.match()
    return  mw.ustring.match( story, scan )
end -- fair()
local function familiar( accept, attempt )
    -- Check string as possible language name or list
    -- Precondition:
    --    accept  -- string; requirement
    --                        lang
    --                        langs
    --                        langW
    --                        langsW
    --                        lang+
    --                        langs+
    --                        langW+
    --                        langsW+
    --    attempt  -- string; to be tested
    -- Postcondition:
    --    Return error keyword, or false
    -- Uses:
    --    >< TemplatePar.extern.Multilingual
    --    Module:Multilingual
    --    Multilingual.isType()
    local r
mw.log("familiar()",accept,attempt)
    if attempt and attempt ~= "" then
        local Multilingual
        if TemplatePar.extern.Multilingual then
            Multilingual = TemplatePar.extern.Multilingual
        else
            local lucky
            lucky, Multilingual = pcall( require, "Module:Multilingual" )
            if type( Multilingual ) == "table" then
                Multilingual = Multilingual.Multilingual()
                TemplatePar.extern.Multilingual = Multilingual
            end
        end
        if type( Multilingual ) == "table" then
            local lazy = accept:find( "W", 1, true )
            if accept:find( "s", 1, true ) then
                local group = mw.text.split( attempt, "%s+" )
                r = false
                for i = 1, #group do
                    if not Multilingual.isLang( group[ i ], lazy ) then
                        r = "invalid"
                        break -- for i
                    end
                end -- for i
            elseif Multilingual.isLang( attempt, lazy ) then
                r = false
            else
                r = "invalid"
            end
        else
            r = "missing"
        end
    elseif accept:find( "+", 1, true ) then
        r = "empty"
    else
        r = false
    end
    return r
end -- familiar()
local function far( accept, attempt )
    -- Check string as possible URL
    -- Precondition:
    --    accept  -- string; requirement
    --                        url
    --                        url+
    --    attempt  -- string; to be tested
    -- Postcondition:
    --    Return error keyword, or false
    -- Uses:
    --    >< TemplatePar.extern.Multilingual
    --    Module:Multilingual
    --    Multilingual.isType()
    local r
    if attempt and attempt ~= "" then
        local URLutil
        if TemplatePar.extern.URLutil then
            URLutil = TemplatePar.extern.URLutil
        else
            local lucky
            lucky, URLutil = pcall( require, "Module:URLutil" )
            if type( URLutil ) == "table" then
                URLutil                    = URLutil.URLutil()
                TemplatePar.extern.URLutil = URLutil
            end
        end
        if type( URLutil ) == "table" then
            if URLutil.isWebURL( attempt ) then
                r = false
            else
                r = "invalid"
            end
        else
            r = "missing"
        end
    elseif accept:find( "+", 1, true ) then
        r = "empty"
    else
        r = false
    end
    return r
end -- far()




Zeile 287: Zeile 407:
     --    mw.text.trim()
     --    mw.text.trim()
     --    facility()
     --    facility()
     --    failsafe()
     --    fair()
     --    containsCJK()
     --    containsCJK()
     local r    = false
     local r    = false
Zeile 356: Zeile 476:
                 r = facility( s, analyze )
                 r = facility( s, analyze )
                 n = true
                 n = true
             elseif s:match( "langW?%+?" ) then
             elseif s:match( "langs?W?%+?" ) then
                 n = "lang"
                r = familiar( s, analyze )
-- lang lang+
                 n = true
-- langW langW+
            elseif s:match( "url%+?" ) then
                r = far( s, analyze )
                n = true
             end
             end
-- datetime+
-- iso8631+
-- line+
             if not n and not r then
             if not n and not r then
                 r = "unknownRule"
                 r = "unknownRule"
Zeile 379: Zeile 504:
     end
     end
     if scan then
     if scan then
         local legal, got = pcall( failsafe, analyze, scan )
         local legal, got = pcall( fair, analyze, scan )
         if legal then
         if legal then
             if not got then
             if not got then
Zeile 414: Zeile 539:
     -- Postcondition:
     -- Postcondition:
     --    Return true iff found
     --    Return true iff found
     local k, v
     local k, v, r
     for k, v in pairs( haystack ) do
     for k, v in pairs( haystack ) do
         if k == needle then
         if k == needle then
             return true
             r = true
         end
         end
     end -- for k, v
     end -- for k, v
     return false
     return r or false
end -- fed()
end -- fed()


Zeile 442: Zeile 567:
         g = TemplatePar.downcase( options )
         g = TemplatePar.downcase( options )
     else
     else
         g = mw.getCurrentFrame()
         TemplatePar.frame = mw.getCurrentFrame()
        g                = TemplatePar.frame
         if light then
         if light then
             g = g:getParent()
             g = g:getParent()
Zeile 486: Zeile 612:
         if type( sub ) == "string" then
         if type( sub ) == "string" then
             sub            = sub:gsub( "%%!", "|" )
             sub            = sub:gsub( "%%!", "|" )
            sub            = sub:gsub( "%%%(%(", "{{" )
                                :gsub( "%%%(%(", "{{" )
            sub            = sub:gsub( "%%%)%)", "}}" )
                                :gsub( "%%%)%)", "}}" )
                                :gsub( "\\n", string.char( 10 ) )
             options.pattern = sub
             options.pattern = sub
             options.key    = nil
             options.key    = nil
Zeile 526: Zeile 653:




local function finalize( submit, options, frame )
local function finalize( submit, options )
     -- Finalize message
     -- Finalize message
     -- Precondition:
     -- Precondition:
Zeile 535: Zeile 662:
     --                options.cat
     --                options.cat
     --                options.template
     --                options.template
    --    frame    -- object, or false
     -- Postcondition:
     -- Postcondition:
     --    Return string or false
     --    Return string or false
Zeile 542: Zeile 668:
     local r = false
     local r = false
     if submit then
     if submit then
        local lazy  = false
        local learn = false
        local show  = false
         local opt, s
         local opt, s
        local lazy = false
        local show = false
         if type( options ) == "table" then
         if type( options ) == "table" then
             opt  = options
             opt  = options
Zeile 551: Zeile 678:
             s    = opt.preview
             s    = opt.preview
             if type( s ) == "string"  and
             if type( s ) == "string"  and
                s ~= ""  and  s ~= "0"  and  s ~= "-" then
              s ~= ""  and  s ~= "0"  and  s ~= "-" then
                local sniffer = "{{REVISIONID}}"
                 if lazy then
                 if lazy then
                     show = ""
                     show = ""
                     lazy = false
                     lazy = false
                 end
                 end
                 if not frame then
                 if not TemplatePar.frame then
                     frame = mw.getCurrentFrame()
                     TemplatePar.frame = mw.getCurrentFrame()
                 end
                 end
                 if frame:preprocess( "{{REVISIONID}}" ) == "" then
                 if TemplatePar.frame:preprocess( sniffer ) == "" then
                     if s == "1" then
                     if s == "1" then
                         show = "*"
                         show = "*"
Zeile 565: Zeile 693:
                         show = s
                         show = s
                     end
                     end
                    learn = true
                 end
                 end
             end
             end
Zeile 581: Zeile 710:
             local i
             local i
             if not show  or  show == "*" then
             if not show  or  show == "*" then
                 show = "<span class=\"error\">@@@</span>"
                 local e = mw.html.create( "span" )
                                :attr( "class", "error" )
                                :wikitext( "@@@" )
                if learn then
                    local max  = 1000000000
                    local id  = math.floor( os.clock() * max )
                    local sign = string.format( "error_%d", id )
                    local btn  = mw.html.create( "span" )
                    local top  = mw.html.create( "div" )
                    e:attr( "id", sign )
                    btn:css( { ["background"]      = "#FFFF00",
                              ["border"]          = "#FF0000 3px solid",
                              ["font-weight"]    = "bold",
                              ["padding"]        = "2px",
                              ["text-decoration"] = "none" } )
                      :wikitext( "&gt;&gt;&gt;" )
                    sign = string.format( "[[#%s|%s]]",
                                          sign,  tostring( btn ) )
                    top:wikitext( sign, "&#160;", submit )
                    mw.addWarning( tostring( top ) )
                end
                show = tostring( e )
             end
             end
             i = show:find( "@@@", 1, true )
             i = show:find( "@@@", 1, true )
Zeile 593: Zeile 743:
                 r = show
                 r = show
             end
             end
        end
        if learn and r then
            -- r = fatal( r )
         end
         end
         s = opt.cat
         s = opt.cat
         if type( s ) == "string" then
         if type( s ) == "string" then
            local link
             if opt.errNS then
             if opt.errNS then
                 local ns = mw.title.getCurrentTitle().namespace
                 local ns = mw.title.getCurrentTitle().namespace
Zeile 603: Zeile 757:
                     local spaces = string.format( " %s ", opt.errNS )
                     local spaces = string.format( " %s ", opt.errNS )
                     if spaces:match( space ) then
                     if spaces:match( space ) then
                         opt.errNS = false
                         link = true
                     end
                     end
                 elseif st == "table" then
                 elseif st == "table" then
                     for i = 1, #opt.errNS do
                     for i = 1, #opt.errNS do
                         if opt.errNS[ i ] == ns then
                         if opt.errNS[ i ] == ns then
                             opt.errNS = false
                             link = true
                             break    -- for i
                             break    -- for i
                         end
                         end
                     end -- for i
                     end -- for i
                 end
                 end
            else
                link = true
             end
             end
             if opt.errNS then
             if link then
                 r = ""
                 local cats, i
            else
                 if not r then
                 if not r then
                   r = ""
                   r = ""
Zeile 625: Zeile 780:
                     end
                     end
                 end
                 end
                 local i
                 cats = mw.text.split( s, "%s*#%s*" )
                local cats = mw.text.split( s, "%s*#%s*" )
                 for i = 1, #cats do
                 for i = 1, #cats do
                     s = mw.text.trim( cats[ i ] )
                     s = mw.text.trim( cats[ i ] )
Zeile 804: Zeile 958:
     --                options.mandatory
     --                options.mandatory
     --                options.optional
     --                options.optional
     --    frame    -- object, or false
     --    frame    -- object; #invoke environment, or false
     -- Postcondition:
     -- Postcondition:
     --    Return string with error message as configured;
     --    Return string with error message as configured;
     --            false if valid
     --            false if valid
     -- Uses:
     -- Uses:
    --      < TemplatePar.frame
     --    fold()
     --    fold()
     --    fetch()
     --    fetch()
Zeile 814: Zeile 969:
     --    finalize()
     --    finalize()
     local duty, r
     local duty, r
    if frame then
        TemplatePar.frame = frame
    else
        TemplatePar.frame = mw.getCurrentFrame()
    end
     if type( options ) == "table" then
     if type( options ) == "table" then
         if type( options.mandatory ) ~= "table" then
         if type( options.mandatory ) ~= "table" then
Zeile 836: Zeile 996:
         end
         end
     end
     end
     return finalize( r, options, frame )
     return finalize( r, options )
end -- form()
end -- form()


Zeile 907: Zeile 1.067:
     --            false if valid or no answer permitted
     --            false if valid or no answer permitted
     -- Uses:
     -- Uses:
     --    mw.text.trim()  
     --    mw.text.trim()
     --    format()
     --    format()
     --    failure()
     --    failure()
Zeile 914: Zeile 1.074:
         local story = assignment.args[ access ] or ""
         local story = assignment.args[ access ] or ""
         if type( access ) == "number" then
         if type( access ) == "number" then
             story = mw.text.trim( story )  
             story = mw.text.trim( story )
         end
         end
         if type( options ) ~= "table" then
         if type( options ) ~= "table" then
Zeile 986: Zeile 1.146:
         end
         end
         if r then
         if r then
             r = finalize( r, options, frame )
             r = finalize( r, options )
         else
         else
             s = frame.args[ 1 ] or ""
             s = frame.args[ 1 ] or ""
Zeile 994: Zeile 1.154:
             end
             end
             if action == "valid" then
             if action == "valid" then
                 r = TemplatePar.valid( s, options, frame )
                 r = TemplatePar.valid( s, options )
             elseif action == "assert" then
             elseif action == "assert" then
                 r = TemplatePar.assert( s, "", options )
                 r = TemplatePar.assert( s, "", options )
Zeile 1.104: Zeile 1.264:




TemplatePar.valid = function ( access, options, frame )
TemplatePar.failsafe = function ( assert )
    -- Retrieve versioning and check for compliance
    -- Precondition:
    --    assert  -- string, with required version or "wikidata",
    --                or false
    -- Postcondition:
    --    Returns  string with appropriate version, or false
    local r
    if since == "wikidata" then
        local item = TemplatePar.item
        since = false
        if type( item ) == "number"  and  item > 0 then
            local ent = mw.wikibase.getEntity( string.format( "Q%d",
                                                              item ) )
            if type( ent ) == "table" then
                local vsn = ent:formatPropertyValues( "P348" )
                if type( vsn ) == "table"  and
                  type( vsn.value) == "string"  and
                  vsn.value ~= "" then
                    r = vsn.value
                end
            end
        end
    end
    if not r then
        if not since  or  since <= TemplatePar.serial then
            r = TemplatePar.serial
        else
            r = false
        end
    end
    return r
end -- TemplatePar.failsafe()
 
 
 
TemplatePar.valid = function ( access, options )
     -- Check validity of one particular template parameter
     -- Check validity of one particular template parameter
     -- Precondition:
     -- Precondition:
Zeile 1.110: Zeile 1.306:
     --                string or number
     --                string or number
     --    options  -- table or nil; optional details
     --    options  -- table or nil; optional details
    --    frame    -- object; #invoke environment
     -- Postcondition:
     -- Postcondition:
     --    Return string with error message as configured;
     --    Return string with error message as configured;
     --            false if valid or no answer permitted
     --            false if valid or no answer permitted
     -- Uses:
     -- Uses:
    --    >< TemplatePar.frame
     --    mw.text.trim()
     --    mw.text.trim()
     --    TemplatePar.downcase()
     --    TemplatePar.downcase()
Zeile 1.140: Zeile 1.336:
             params = TemplatePar.downcase( options )
             params = TemplatePar.downcase( options )
         else
         else
             params = frame:getParent()
            if not TemplatePar.frame then
                TemplatePar.frame = mw.getCurrentFrame()
            end
             params = TemplatePar.frame:getParent()
         end
         end
         r = formatted( params, access, options )
         r = formatted( params, access, options )
Zeile 1.179: Zeile 1.378:
     --    furnish()
     --    furnish()
     return furnish( frame, "assert" )
     return furnish( frame, "assert" )
end -- .assert()
end -- p.assert()




Zeile 1.216: Zeile 1.415:
     end
     end
     return r or ""
     return r or ""
end -- .check()
end -- p.check()




Zeile 1.227: Zeile 1.426:
     --    TemplatePar.count()
     --    TemplatePar.count()
     return tostring( TemplatePar.count() )
     return tostring( TemplatePar.count() )
end -- .count()
end -- p.count()




Zeile 1.238: Zeile 1.437:
     --    TemplatePar.countNotEmpty()
     --    TemplatePar.countNotEmpty()
     return tostring( TemplatePar.countNotEmpty() )
     return tostring( TemplatePar.countNotEmpty() )
end -- .countNotEmpty()
end -- p.countNotEmpty()




Zeile 1.244: Zeile 1.443:
function p.match( frame )
function p.match( frame )
     -- Combined analysis of parameters and their values
     -- Combined analysis of parameters and their values
    -- Precondition:
    --    frame  -- object; #invoke environment
     -- Postcondition:
     -- Postcondition:
     --    Return string with error message or ""
     --    Return string with error message or ""
     -- Uses:
     -- Uses:
    --      < TemplatePar.frame
     --    mw.text.trim()
     --    mw.text.trim()
     --    mw.ustring.lower()
     --    mw.ustring.lower()
Zeile 1.266: Zeile 1.468:
     local k, v, s
     local k, v, s
     local params = { }
     local params = { }
    TemplatePar.frame = frame
     for k, v in pairs( frame.args ) do
     for k, v in pairs( frame.args ) do
         if type( k ) == "number" then
         if type( k ) == "number" then
Zeile 1.349: Zeile 1.552:
                 r = failure( "invalid", errValues, options )
                 r = failure( "invalid", errValues, options )
             end
             end
             r = finalize( r, options, frame )
             r = finalize( r, options )
         end
         end
     end
     end
     return r or ""
     return r or ""
end -- .match()
end -- p.match()




Zeile 1.366: Zeile 1.569:
     --    furnish()
     --    furnish()
     return furnish( frame, "valid" )
     return furnish( frame, "valid" )
end -- .valid()
end -- p.valid()
 
 
 
p.failsafe = function ( frame )
    -- Check or retrieve version information
    -- Precondition:
    --    frame  -- object; #invoke environment
    -- Postcondition:
    --    Return string with error message or ""
    -- Uses:
    --    TemplatePar.failsafe()
    local s = type( frame )
    local since
    if s == "table" then
        since = frame.args[ 1 ]
    elseif s == "string" then
        since = frame
    end
    if since then
        since = mw.text.trim( since )
        if since == "" then
            since = false
        end
    end
    return TemplatePar.failsafe( since )  or  ""
end -- p.failsafe()




Zeile 1.375: Zeile 1.604:
     --    Return table with functions
     --    Return table with functions
     return TemplatePar
     return TemplatePar
end -- .TemplatePar()
end -- p.TemplatePar()






return p
return p
Anonymer Benutzer

Navigationsmenü