Nicht angemeldeter Benutzer - Bearbeiten von Seiten ist nur als angemeldeter Benutzer möglich.

Änderungen

Zur Navigation springen Zur Suche springen
6.211 Bytes hinzugefügt ,  10:26, 6. Nov. 2019
K
39 Versionen importiert: Import der Hilfe zu TemplateData aus der deutschen Wikipedia [https://de.wikipedia.org/w/index.php?title=Hilfe:TemplateData/JSON&oldid=189058032]
Zeile 1: Zeile 1: −
--[=[ 2015-04-04
+
local Shortcuts = { suite  = "Shortcuts",
Module:Shortcuts
+
                    serial = "2019-08-01",
 +
                    item  = 0 }
 +
--[=[
 +
Support shortcut redirects
 
]=]
 
]=]
 
+
local Failsafe = Shortcuts
       
-- local globals
 
-- local globals
local Config
+
local Current = { rule = { } }
local Current = { }
   
local Errors  = false
 
local Errors  = false
 
local Sort    = false
 
local Sort    = false
Zeile 69: Zeile 71:  
     return r
 
     return r
 
end -- facet()
 
end -- facet()
 +
 +
 +
 +
local function facilitated( attempt )
 +
    -- Check whether Config string is a text formatting pattern
 +
    --    attempt  -- string, with format pattern
 +
    -- Throws error with message, else does nothing
 +
    local s = Config[ attempt ]
 +
    if type( s ) ~= "string"  or
 +
      not s:find( "%s", 1, true ) then
 +
        error( string.format( "/config '%s' invalid", attempt ) )
 +
    end
 +
end -- facilitated()
      Zeile 105: Zeile 120:       −
local function failsafe( attempt )
+
local function faculty( adjust )
     -- Check whether Config string may is a text formatting pattern
+
     -- Test template arg for boolean
     --    attempt -- string, with format pattern
+
     --    adjust -- string or nil
     -- Throws error with message, else does nothing
+
     -- Returns boolean
     local s = Config[ attempt ]
+
     local s = type( adjust )
     if type( s ) ~= "stringor
+
    local r
      not s:find( "%s", 1, true ) then
+
     if s == "string" then
         error( string.format( "/config '%s' invalid", attempt ) )
+
        r = mw.text.trim( adjust )
 +
        r = ( r ~= ""  and  r ~= "0" )
 +
    elseif s == "boolean" then
 +
         r = adjust
 +
    else
 +
        r = false
 +
    end
 +
    return r
 +
end -- faculty()
 +
 
 +
 
 +
 
 +
local function failure( assigned, about )
 +
    -- Add one message to Errors
 +
    --    assigned  -- string, with shortcut page name
 +
    --    about    -- string, with error keyword
 +
    if type( Errors ) ~= "table" then
 +
        Errors = { }
 
     end
 
     end
end -- failsafe()
+
    Errors[ assigned ] = about
 +
end -- failure()
      Zeile 133: Zeile 166:  
     return mw.text.trim( r )
 
     return mw.text.trim( r )
 
end -- fair()
 
end -- fair()
 +
 +
 +
 +
local function fallback( access, alt )
 +
    -- Retrieve message text
 +
    --    access  -- string, with message ID
 +
    --    alt    -- string, with plain message, if no access
 +
    -- Returns string, with any message
 +
    local r = Config[ access ]
 +
    if type( r ) ~= "string" then
 +
        r = alt  or  "***** UNKNOWN MESSAGE " .. access .. " *****"
 +
    end
 +
    return r
 +
end -- fallback()
      Zeile 140: Zeile 187:  
     --    alert  -- string, with message, or other data
 
     --    alert  -- string, with message, or other data
 
     -- Returns message string with markup
 
     -- Returns message string with markup
 +
    local elem = mw.html.create( "span" )
 +
                        :addClass( "error" )
 
     local ecat = mw.message.new( "Scribunto-common-error-category" )
 
     local ecat = mw.message.new( "Scribunto-common-error-category" )
     local r = type( alert )
+
     local r   = type( alert )
 
     if r == "string" then
 
     if r == "string" then
 
         r = alert
 
         r = alert
Zeile 147: Zeile 196:  
         r = "???? " .. r
 
         r = "???? " .. r
 
     end
 
     end
     if ecat:isBlank() then
+
    elem:wikitext( string.format( "FATAL LUA ERROR %s", r ) )
        ecat = ""
+
    r = tostring( elem )
    else
+
     if not ecat:isBlank() then
         ecat = string.format( "[[Category:%s]]", ecat:plain() )
+
         ecat = string.format( "%s[[Category:%s]]", r, ecat:plain() )
 
     end
 
     end
    r = string.format( "<span class=\"error\">FATAL LUA ERROR %s</span>",
  −
                      r )
  −
        .. ecat
   
     return r
 
     return r
 
end -- fatal()
 
end -- fatal()
Zeile 165: Zeile 211:  
     --    absent  -- boolean, hide message, trigger category
 
     --    absent  -- boolean, hide message, trigger category
 
     -- Returns message with markup
 
     -- Returns message with markup
     local r = string.format( "<span class=\"error\">%s</span>",
+
     local e = mw.html.create( "span" )
                            alert or "???" )
+
                    :addClass( "error" )
 +
                    :wikitext( alert or "???" )
 +
    local r = tostring( e )
 
     if absent  and  type( Config ) == "table" then
 
     if absent  and  type( Config ) == "table" then
 
         if type( Config.suppress ) == "string" then
 
         if type( Config.suppress ) == "string" then
             failsafe( "suppress" )
+
             facilitated( "suppress" )
 
             r = string.format( Config.suppress, r )
 
             r = string.format( Config.suppress, r )
 
         end
 
         end
Zeile 178: Zeile 226:  
     return r
 
     return r
 
end -- fault()
 
end -- fault()
  −
  −
  −
local function failure( assigned, about )
  −
    -- Add one message to Errors
  −
    --    assigned  -- string, with shortcut page name
  −
    --    about    -- string, with error keyword
  −
    if type( Errors ) ~= "table" then
  −
        Errors = { }
  −
    end
  −
    Errors[ assigned ] = about
  −
end -- failure()
        Zeile 233: Zeile 269:  
     if page.exists then
 
     if page.exists then
 
         if page.isRedirect then
 
         if page.isRedirect then
            local redirect, say
   
             local story = page:getContent()
 
             local story = page:getContent()
 
             local shift = story:match( "^#[^%[]+%[%[([^%]\n]+)%]%]" )
 
             local shift = story:match( "^#[^%[]+%[%[([^%]\n]+)%]%]" )
             if not shift  or shift:match( "%%%x%x" ) then
+
            local redirect
 +
             if not shift  or
 +
              shift:match( "%%%x%x" ) then
 
                 redirect = false
 
                 redirect = false
 
             else
 
             else
Zeile 242: Zeile 279:  
             end
 
             end
 
             if not redirect then
 
             if not redirect then
                 if type( Config.sayBadLink ) == "string" then
+
                 failure( alone,
                    say = Config.sayBadLink
+
                        fallback( "sayBadLink", "bad link encoding" ) )
                else
  −
                    say = "bad link encoding"
  −
                end
  −
                failure( alone, say )
   
             elseif mw.title.equals( Current.page, redirect ) then
 
             elseif mw.title.equals( Current.page, redirect ) then
 
                 for k, v in pairs( achieved ) do
 
                 for k, v in pairs( achieved ) do
 
                     if mw.title.equals( page, v ) then
 
                     if mw.title.equals( page, v ) then
                         if type( Config.sayDuplicated ) == "string" then
+
                         failure( alone,
                            say = Config.sayDuplicated
+
                                fallback( "sayDuplicated",
                        else
+
                                          "duplicated" ) )
                            say = "duplicated"
  −
                        end
  −
                        failure( alone, say )
   
                         page = false
 
                         page = false
 
                         break    -- for k, v
 
                         break    -- for k, v
Zeile 265: Zeile 295:  
                 end
 
                 end
 
                 if Current.nsns == Current.nsn
 
                 if Current.nsns == Current.nsn
 +
                  and  not Current.leave
 
                   and  Config.signature
 
                   and  Config.signature
 
                   and  not story:find( Config.signature, 15 ) then
 
                   and  not story:find( Config.signature, 15 ) then
                     if type( Config.signal ) == "string" then
+
                     failure( alone,
                        say = Config.signal
+
                            fallback( "signal",
                    else
+
                                      ".signature (category) missing" )
                        say = ".signature (category) missing"
+
                          )
                    end
  −
                    failure( alone, say )
   
                 end
 
                 end
 
             else
 
             else
                 if type( Config.sayTarget ) == "string" then
+
                 failure( alone,
                    say = Config.sayTarget
+
                        fallback( "sayTarget", "wrong target" ) )
                else
  −
                    say = "wrong target"
  −
                end
  −
                failure( alone, say )
   
             end
 
             end
 
         else
 
         else
             if type( Config.sayRegular ) == "string" then
+
             failure( alone,  fallback( "sayRegular", "regular page" ) )
                say = Config.sayRegular
  −
            else
  −
                say = "regular page"
  −
            end
  −
            failure( alone, say )
   
         end
 
         end
 
     else
 
     else
         if type( Config.sayMissing ) == "string" then
+
         failure( alone,  fallback( "sayMissing", "missing" ) )
            say = Config.sayMissing
  −
        else
  −
            say = "missing"
  −
        end
  −
        failure( alone, say )
   
     end
 
     end
 
end -- flag()
 
end -- flag()
Zeile 309: Zeile 324:  
     local r = "\n|}"
 
     local r = "\n|}"
 
     local collect = { }
 
     local collect = { }
     local n
+
     local n, previous
 
     if type( alone ) == "number" then
 
     if type( alone ) == "number" then
 
         n = factory( account, alone, collect )
 
         n = factory( account, alone, collect )
Zeile 333: Zeile 348:  
             shortcut = string.format( "[[%s]]", v.shortcut )
 
             shortcut = string.format( "[[%s]]", v.shortcut )
 
             second  = string.format( "[[:%s]]", v.shift )
 
             second  = string.format( "[[:%s]]", v.shift )
             r       = fiat( shortcut, second ) .. r
+
            if v.shortcut == previous then
 +
                failure( previous,
 +
                        fallback( "sayDuplicated", "duplicated" ) )
 +
            end
 +
            previous = v.shortcut
 +
             r = fiat( shortcut, second ) .. r
 
         end    -- for k, v
 
         end    -- for k, v
 
     end
 
     end
Zeile 359: Zeile 379:  
     end
 
     end
 
     if n == 0 then
 
     if n == 0 then
         if type( Config.sayNoPage ) == "string" then
+
         r = fallback( "sayNoPage", "No target page" )
            r = Config.sayNoPage
  −
        else
  −
            r = "No target page"
  −
        end
   
     else
 
     else
 
         if type( arglist.space ) == "string" then
 
         if type( arglist.space ) == "string" then
Zeile 380: Zeile 396:  
                 end
 
                 end
 
             else
 
             else
                 if type( Config.sayNoNamespace ) == "string" then
+
                 r = fallback( "sayNoNamespace", "No target namespace" )
                    r = Config.sayNoNamespace
  −
                else
  −
                    r = "No target namespace"
  −
                end
   
             end
 
             end
 
         end
 
         end
Zeile 410: Zeile 422:  
             end
 
             end
 
             if type( t ) ~= "table" then
 
             if type( t ) ~= "table" then
                if type( Config.sayNamespaceOff ) == "string" then
+
                 r = string.format( "%d (%s) * %s",
                    r = Config.sayNamespaceOff
+
                                  nsn,
                else
+
                                  space,
                    r = "Namespace not configured"
+
                                  fallback( "sayNamespaceOff",
                end
+
                                            "Namespace not configured" )
                 r = string.format( "%d (%s) * %s", nsn, space, r )
+
                                )
 
             end
 
             end
 
         end
 
         end
Zeile 451: Zeile 463:  
                 end
 
                 end
 
             else
 
             else
                 local say
+
                 shortcuts = fault( fallback( "sayUnregistered",
                if type( Config.sayUnregistered ) == "string" then
+
                                            "no shortcuts registered" ),
                    say = Config.sayUnregistered
+
                                  false )
                else
  −
                    say = "no shortcuts registered"
  −
                end
  −
                shortcuts = fault( say, false )
   
             end
 
             end
 
             r = r .. fiat( s, shortcuts )
 
             r = r .. fiat( s, shortcuts )
Zeile 475: Zeile 483:  
     local pages    = { }
 
     local pages    = { }
 
     local shortcuts = face( arglist.shortcuts )
 
     local shortcuts = face( arglist.shortcuts )
 +
    local style    = Config.style
 
     local got, r
 
     local got, r
 
     if Config.show then
 
     if Config.show then
         failsafe( "show" )
+
         facilitated( "show" )
 
         r = string.format( Config.show, shortcuts )
 
         r = string.format( Config.show, shortcuts )
 
     end
 
     end
     if Config.style and not Config.light then
+
     if Current.style  and  Config[ Current.style ] then
        failsafe( "style" )
+
        style = Config[ Current.style ]
        r = string.format( Config.style, r )
+
    elseif Current.rule then
        if r:find( "###", 16, true ) then
+
        got = type( Current.rule.styling )
            local s = shortcuts
+
        if got == "boolean" then
            local k = s:find( ",", 3, true )
+
            style = false
            if k then
+
        elseif got == "string" then
                s = s:sub( 1,  k - 1 )
+
            style = Config[ Current.rule.styling ]
 +
        end
 +
    end
 +
    if style then
 +
        if not Config.light then
 +
            local s
 +
            facilitated( "style" )
 +
            if style:find( ".sub.", 8, true ) then
 +
                style = style:gsub( "%.sub%.", "-sub" )
 +
            end
 +
            if style:find( "-shortcut:", 16, true ) then
 +
                if Current.page.isSubpage then
 +
                    s = "%1line-height: 0; top: -2.5em%2"
 +
                else
 +
                    s = "%1top: -1em%2"
 +
                end
 +
                style = style:gsub( "([; '])%-shortcut:%s*top([; '])",
 +
                                    s )
 +
                s = "%sdata-shortcut-clear-right='1'"
 +
                if style:find( s ) then
 +
                    e = mw.html.create( "div" )
 +
                    e:css( { ["clear"]  = "right",
 +
                            ["height"] = "0" } )
 +
                    style = style:gsub( s, "" ) .. tostring( e )
 +
                end
 +
            end
 +
            r = string.format( style, r )
 +
            if r:find( "###", 16, true ) then
 +
                local k = shortcuts:find( ",", 3, true )
 +
                s = shortcuts
 +
                if k then
 +
                    s = s:sub( 1,  k - 1 )
 +
                end
 +
                r = r:gsub( "###", s, 1 )
 
             end
 
             end
            r = r:gsub( "###", s, 1 )
   
         end
 
         end
 +
    else
 +
        r = ""
 
     end
 
     end
 
     got = shortcuts:gsub( "<s>[^<]+</s>", "" )
 
     got = shortcuts:gsub( "<s>[^<]+</s>", "" )
Zeile 502: Zeile 545:  
     if Errors then
 
     if Errors then
 
         local s = "Shortcuts * "
 
         local s = "Shortcuts * "
 +
        local t
 
         for k, v in pairs( Errors ) do
 
         for k, v in pairs( Errors ) do
             s = string.format( "%s <u>[[%s]]</u>:&#160;%s", s, k, v )
+
            t = mw.title.new( k )
 +
             s = string.format( "%s <u>[%s %s]</u>:&#160;%s",
 +
                              s,
 +
                              t:fullUrl( { redirect = "no" } ),
 +
                              k,
 +
                              v )
 
         end    -- for k, v
 
         end    -- for k, v
 
         r = r .. fault( s, true )
 
         r = r .. fault( s, true )
Zeile 517: Zeile 566:  
     --        .self      -- string, target page
 
     --        .self      -- string, target page
 
     --        .shortcuts  -- string, comma separated list of shortcuts
 
     --        .shortcuts  -- string, comma separated list of shortcuts
 +
    --        .style      -- string, particular style ID
 +
    --        .loose      -- boolean, ignore undefined shortcuts
 
     -- Throws error with message, else returns string with text
 
     -- Throws error with message, else returns string with text
 
     local l, t, sub
 
     local l, t, sub
Zeile 576: Zeile 627:  
                     end    -- for k, v
 
                     end    -- for k, v
 
                 end
 
                 end
                 if type( t ) == "table" then
+
                 if args.service == "template" then
                    sub = Current.page.text
+
                    if type( Config.rules ) == "table" then
                    if type( t[ sub ] ) == "string" then
+
                        local rules = Config.rules[ Current.nsn ]
                        if args.shortcuts  and not Config.locally then
+
                        if type( rules ) == "table" then
 +
                            local seek = Current.page.text
 +
                            local scope
 +
                            for k, v in pairs( rules ) do
 +
                                if type( v ) == "table" then
 +
                                    if type( v.sub ) ~= "string"
 +
                                      or mw.ustring.match( seek,
 +
                                                            v.sub ) then
 +
                                        Current.rule.styling = v.styling
 +
                                        Current.rule.locally = v.locally
 +
                                    end
 +
                                end
 +
                            end    -- for k, v
 +
                        end
 +
                    end
 +
                    if type( t ) == "table" then
 +
                        sub = Current.page.text
 +
                        if type( t[ sub ] ) == "string" then
 +
                            if args.shortcuts  and
 +
                              not Config.locally then
 +
                                args.shortcuts = false
 +
                                r              = fallback( "sayNoLocals",
 +
                                                  "'1=' not permitted" )
 +
                            else
 +
                                args.shortcuts = t[ sub ]
 +
                                if Current.nsn == Current.nsnt then
 +
                                    args.shortcuts
 +
                                                = fair( args.shortcuts )
 +
                                end
 +
                            end
 +
                        elseif Current.rule.locally then
 
                             args.shortcuts = false
 
                             args.shortcuts = false
                            r              = "'1=' not permitted"
  −
                        else
  −
                            args.shortcuts = t[ sub ]
  −
                            if Current.nsn == Current.nsnt then
  −
                                args.shortcuts = fair( args.shortcuts )
  −
                            end
   
                         end
 
                         end
 +
                    elseif Current.rule.locally then
 +
                        args.shortcuts = false
 
                     end
 
                     end
                end
  −
                if args.service == "template" then
   
                     if type( args.shortcuts ) == "string" then
 
                     if type( args.shortcuts ) == "string" then
 +
                        local suitable  = Config.patternSuitable or ""
 +
                        local syntactic = "[_#%{%}|]"
 +
                        suitable      = string.format( "^[ -~%s]+$",
 +
                                                        suitable )
 
                         args.shortcuts = mw.text.trim( args.shortcuts )
 
                         args.shortcuts = mw.text.trim( args.shortcuts )
 
                         if args.shortcuts == "" then
 
                         if args.shortcuts == "" then
                             r = "no shortcuts"
+
                             r = fallback( "sayNoShortcuts",
                         elseif ( Current.nsn == 2 or Current.nsn == 3 )
+
                                          "no shortcuts" )
                               and  not args.shortcuts:find( "/" ) then
+
                         elseif Current.leave  and
 +
                               not args.shortcuts:find( "/" ) then
 
                             leave = true
 
                             leave = true
 +
                        elseif mw.ustring.match( args.shortcuts,
 +
                                                suitable )  and
 +
                              not args.shortcuts:match( syntactic ) then
 +
                            lucky = true
 
                         else
 
                         else
                             lucky = true
+
                             r = fallback( "sayInvalidChar",
 +
                                      "shortcut with invalid character" )
 
                         end
 
                         end
 
                     elseif Current.page.prefixedText == Config.skip then
 
                     elseif Current.page.prefixedText == Config.skip then
Zeile 605: Zeile 690:  
                         args.leave    = true
 
                         args.leave    = true
 
                         lucky          = true
 
                         lucky          = true
 +
                    elseif args.loose then
 +
                        leave = true
 
                     elseif Config.locally then
 
                     elseif Config.locally then
                         if type( Config.sayUnknown ) == "string" then
+
                         r = fallback( "sayUnknown",
                            r = Config.sayUnknown
+
                                      "Shortcuts template:"
                        else
+
                                      .. " page not registered,"
                            r = "Shortcuts template:"
+
                                      .. " '1=' missing" )
                                .. " page not registered, '1=' missing"
  −
                        end
   
                     end
 
                     end
                     if Current.page.id == 6167366 then
+
                     if not lucky  and  Current.rule.locally then
 +
                        lucky = true
 
                         leave = true
 
                         leave = true
 
                     end
 
                     end
Zeile 626: Zeile 712:  
                 r = ""  -- NOOP
 
                 r = ""  -- NOOP
 
             elseif args.service == "template" then
 
             elseif args.service == "template" then
 +
                Current.style  = args.style
 
                 r = follow( args )
 
                 r = follow( args )
 
             elseif args.service == "trows" then
 
             elseif args.service == "trows" then
Zeile 654: Zeile 741:  
     local pars  = frame:getParent().args
 
     local pars  = frame:getParent().args
 
     if params.service == "template" then
 
     if params.service == "template" then
 +
        params.loose    = faculty( pars.loose )
 
         params.shortcuts = pars[ 1 ]
 
         params.shortcuts = pars[ 1 ]
         if pars.light then
+
         if faculty( pars.light ) and
            params.light = ( pars.light == "1" )
+
          params.light and
            if params.light and frame.args.shortcut then
+
          frame.args.shortcut then
                params.shortcuts = frame.args.shortcut
+
            params.shortcuts = frame.args.shortcut
 +
        end
 +
        if params.shortcuts then
 +
            params.shortcuts = mw.text.trim( params.shortcuts )
 +
            if params.shortcuts == "" then
 +
                params.shortcuts = false
 
             end
 
             end
 
         end
 
         end
 +
        params.style = pars.style
 
     elseif params.service == "trows" then
 
     elseif params.service == "trows" then
 
         local k, v, s
 
         local k, v, s
Zeile 693: Zeile 787:  
     return r
 
     return r
 
end -- framed()
 
end -- framed()
 +
 +
 +
 +
Failsafe.failsafe = function ( atleast )
 +
    -- Retrieve versioning and check for compliance
 +
    -- Precondition:
 +
    --    atleast  -- string, with required version or "wikidata" or "~"
 +
    --                or false
 +
    -- Postcondition:
 +
    --    Returns  string  -- with queried version, also if problem
 +
    --              false  -- if appropriate
 +
    local last  = ( atleast == "~" )
 +
    local since = atleast
 +
    local r
 +
    if last  or  since == "wikidata" then
 +
        local item = Failsafe.item
 +
        since = false
 +
        if type( item ) == "number"  and  item > 0 then
 +
            local entity = mw.wikibase.getEntity( string.format( "Q%d",
 +
                                                                item ) )
 +
            if type( entity ) == "table" then
 +
                local vsn = entity:formatPropertyValues( "P348" )
 +
                if type( vsn ) == "table"  and
 +
                  type( vsn.value ) == "string"  and
 +
                  vsn.value ~= "" then
 +
                    if last  and  vsn.value == Failsafe.serial then
 +
                        r = false
 +
                    else
 +
                        r = vsn.value
 +
                    end
 +
                end
 +
            end
 +
        end
 +
    end
 +
    if type( r ) == "nil" then
 +
        if not since  or  since <= Failsafe.serial then
 +
            r = Failsafe.serial
 +
        else
 +
            r = false
 +
        end
 +
    end
 +
    return r
 +
end -- Failsafe.failsafe()
      Zeile 701: Zeile 838:  
function p.template( frame )
 
function p.template( frame )
 
     return  framed( frame, "template" )  or  ""
 
     return  framed( frame, "template" )  or  ""
end -- p.template
+
end -- .template
    
function p.total( frame )
 
function p.total( frame )
 
     return  framed( frame, "total" )
 
     return  framed( frame, "total" )
end -- p.total
+
end -- .total
    
function p.trows( frame )
 
function p.trows( frame )
 
     return  framed( frame, "trows" )
 
     return  framed( frame, "trows" )
end -- p.trows
+
end -- .trows
    
function p.twoletters( frame )
 
function p.twoletters( frame )
 
     return  framed( frame, "twoletters" )
 
     return  framed( frame, "twoletters" )
end -- p.twoletters
+
end -- .twoletters
    
function p.test( args )
 
function p.test( args )
Zeile 724: Zeile 861:  
     local lucky, r = pcall( forward, args )
 
     local lucky, r = pcall( forward, args )
 
     return r
 
     return r
end -- p.test()
+
end -- .test()
 +
 
 +
p.failsafe = function ( frame )
 +
    -- Versioning interface
 +
    local s = type( frame )
 +
    local since
 +
    if s == "table" then
 +
        since = frame.args[ 1 ]
 +
    elseif s == "string" then
 +
        since = frame
 +
    end
 +
    if since then
 +
        since = mw.text.trim( since )
 +
        if since == "" then
 +
            since = false
 +
        end
 +
    end
 +
    return Failsafe.failsafe( since )  or  ""
 +
end -- .failsafe
 +
 
 +
p.Shortcuts = function ()
 +
    -- Module interface
 +
    return Shortcuts
 +
end -- .Shortcuts
    
return p
 
return p
Cookies helfen uns bei der Bereitstellung von imedwiki. Durch die Nutzung von imedwiki erklärst du dich damit einverstanden, dass wir Cookies speichern.

Navigationsmenü