<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wiki.onlyfulk.com/history/Modul:Shortcuts?feed=atom</id>
	<title>Modul:Shortcuts - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.onlyfulk.com/history/Modul:Shortcuts?feed=atom"/>
	<link rel="alternate" type="text/html" href="https://wiki.onlyfulk.com/history/Modul:Shortcuts"/>
	<updated>2026-04-29T00:08:46Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in Tobinator-Wiki</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://wiki.onlyfulk.com/index.php?title=Modul:Shortcuts&amp;diff=1928&amp;oldid=prev</id>
		<title>Wiki SysAdm: Schützte „Modul:Shortcuts“ ([Bearbeiten=Nur Administratoren erlauben] (unbeschränkt) [Verschieben=Nur Administratoren erlauben] (unbeschränkt))</title>
		<link rel="alternate" type="text/html" href="https://wiki.onlyfulk.com/index.php?title=Modul:Shortcuts&amp;diff=1928&amp;oldid=prev"/>
		<updated>2025-02-26T23:34:50Z</updated>

		<summary type="html">&lt;p&gt;Schützte „&lt;a href=&quot;/Modul:Shortcuts&quot; title=&quot;Modul:Shortcuts&quot;&gt;Modul:Shortcuts&lt;/a&gt;“ ([Bearbeiten=Nur Administratoren erlauben] (unbeschränkt) [Verschieben=Nur Administratoren erlauben] (unbeschränkt))&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;de&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Nächstältere Version&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Version vom 27. Februar 2025, 01:34 Uhr&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;de&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(kein Unterschied)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Wiki SysAdm</name></author>
	</entry>
	<entry>
		<id>https://wiki.onlyfulk.com/index.php?title=Modul:Shortcuts&amp;diff=1172&amp;oldid=prev</id>
		<title>UltimateG4ming: Die Seite wurde neu angelegt: „local Shortcuts = { suite  = &quot;Shortcuts&quot;,                     serial = &quot;2019-08-01&quot;,                     item   = 0 } --[=[ Support shortcut redirects ]=] local Failsafe = Shortcuts   -- local globals local Current = { rule = { } } local Errors  = false local Sort    = false    local function face( adjust )     -- Unlink string     --     adjust  -- string, with some shortcuts     -- Returns unlinked shortcuts     return adjust:gsub( &quot;%[%[&quot;, &quot;&quot; )…“</title>
		<link rel="alternate" type="text/html" href="https://wiki.onlyfulk.com/index.php?title=Modul:Shortcuts&amp;diff=1172&amp;oldid=prev"/>
		<updated>2025-02-24T22:20:51Z</updated>

		<summary type="html">&lt;p&gt;Die Seite wurde neu angelegt: „local Shortcuts = { suite  = &amp;quot;Shortcuts&amp;quot;,                     serial = &amp;quot;2019-08-01&amp;quot;,                     item   = 0 } --[=[ Support shortcut redirects ]=] local Failsafe = Shortcuts   -- local globals local Current = { rule = { } } local Errors  = false local Sort    = false    local function face( adjust )     -- Unlink string     --     adjust  -- string, with some shortcuts     -- Returns unlinked shortcuts     return adjust:gsub( &amp;quot;%[%[&amp;quot;, &amp;quot;&amp;quot; )…“&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local Shortcuts = { suite  = &amp;quot;Shortcuts&amp;quot;,&lt;br /&gt;
                    serial = &amp;quot;2019-08-01&amp;quot;,&lt;br /&gt;
                    item   = 0 }&lt;br /&gt;
--[=[&lt;br /&gt;
Support shortcut redirects&lt;br /&gt;
]=]&lt;br /&gt;
local Failsafe = Shortcuts&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- local globals&lt;br /&gt;
local Current = { rule = { } }&lt;br /&gt;
local Errors  = false&lt;br /&gt;
local Sort    = false&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function face( adjust )&lt;br /&gt;
    -- Unlink string&lt;br /&gt;
    --     adjust  -- string, with some shortcuts&lt;br /&gt;
    -- Returns unlinked shortcuts&lt;br /&gt;
    return adjust:gsub( &amp;quot;%[%[&amp;quot;, &amp;quot;&amp;quot; )&lt;br /&gt;
                 :gsub( &amp;quot;%]%]&amp;quot;, &amp;quot;&amp;quot; )&lt;br /&gt;
end -- face()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function faces( any )&lt;br /&gt;
    -- Retrieve single shortcut names&lt;br /&gt;
    --     any  -- string, with shortcut name list&lt;br /&gt;
    -- Returns table with shortcut page names&lt;br /&gt;
    local s = any:gsub( &amp;quot;&amp;lt;[^&amp;gt;]+&amp;gt;&amp;quot;, &amp;quot;,&amp;quot; )&lt;br /&gt;
    local r = mw.text.split( s, &amp;quot;%s*,%s*&amp;quot; )&lt;br /&gt;
    for k, v in pairs( r ) do&lt;br /&gt;
        if mw.text.trim( v ) == &amp;quot;&amp;quot; then&lt;br /&gt;
            r[ k ] = nil&lt;br /&gt;
        end&lt;br /&gt;
    end    -- for k, v&lt;br /&gt;
    return r&lt;br /&gt;
end -- faces()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function facet( area, assign, assigned )&lt;br /&gt;
    -- Create mapping shortcut-&amp;gt;target&lt;br /&gt;
    --     area      -- string, with target namespace name and colon&lt;br /&gt;
    --     assign    -- string, with target page name&lt;br /&gt;
    --     assigned  -- string, with shortcut page name&lt;br /&gt;
    -- Returns table with entry&lt;br /&gt;
    --     .shift     -- string, with target page name&lt;br /&gt;
    --     .shortcut  -- string, with shortcut page name&lt;br /&gt;
    --     .nsn       -- number, of shortcut namespace&lt;br /&gt;
    --     .sort      -- string, with sortable shortcut page title&lt;br /&gt;
    local space, subject = assigned:match( &amp;quot;^([^:]+):(.+)$&amp;quot; )&lt;br /&gt;
    local r = { }&lt;br /&gt;
    r.shift    = area .. assign&lt;br /&gt;
    r.shortcut = assigned&lt;br /&gt;
    if space then&lt;br /&gt;
        local o = mw.site.namespaces[ space ]&lt;br /&gt;
        if o then&lt;br /&gt;
            r.nsn = o.id&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if not r.nsn then&lt;br /&gt;
        r.nsn   = 0&lt;br /&gt;
        subject = assigned&lt;br /&gt;
    end&lt;br /&gt;
    if Sort then&lt;br /&gt;
        subject = Sort.lex( subject, &amp;quot;latin&amp;quot;, false )&lt;br /&gt;
    end&lt;br /&gt;
    r.sort = string.upper( subject )&lt;br /&gt;
    return r&lt;br /&gt;
end -- facet()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function facilitated( attempt )&lt;br /&gt;
    -- Check whether Config string is a text formatting pattern&lt;br /&gt;
    --     attempt  -- string, with format pattern&lt;br /&gt;
    -- Throws error with message, else does nothing&lt;br /&gt;
    local s = Config[ attempt ]&lt;br /&gt;
    if type( s ) ~= &amp;quot;string&amp;quot;  or&lt;br /&gt;
       not s:find( &amp;quot;%s&amp;quot;, 1, true ) then&lt;br /&gt;
        error( string.format( &amp;quot;/config &amp;#039;%s&amp;#039; invalid&amp;quot;, attempt ) )&lt;br /&gt;
    end&lt;br /&gt;
end -- facilitated()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function factory( account, alone, assembly )&lt;br /&gt;
    -- Retrieve mappings shortcut-&amp;gt;target for entire target namespace&lt;br /&gt;
    --     account   -- string, with module name&lt;br /&gt;
    --     alone     -- number, of namespace&lt;br /&gt;
    --     assembly  -- table, collecting assignments&lt;br /&gt;
    -- Extending assembly&lt;br /&gt;
    -- Returns number of target pages&lt;br /&gt;
    local space = mw.site.namespaces[ alone ]&lt;br /&gt;
    local r = 0&lt;br /&gt;
    if space then&lt;br /&gt;
        local got&lt;br /&gt;
        local sub = string.format( &amp;quot;%s/%d&amp;quot;, account, alone )&lt;br /&gt;
        local l, t = pcall( mw.loadData, sub )&lt;br /&gt;
        if type( t ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
            if space.id == 0 then&lt;br /&gt;
                space = &amp;quot;&amp;quot;&lt;br /&gt;
            else&lt;br /&gt;
                space = space.name .. &amp;quot;:&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
            for k, v in pairs( t ) do&lt;br /&gt;
                got = faces( face( v ) )&lt;br /&gt;
                for i, s in pairs( got ) do&lt;br /&gt;
                    table.insert( assembly,  facet( space, k, s ) )&lt;br /&gt;
                end    -- for i, s&lt;br /&gt;
                r = r + 1&lt;br /&gt;
            end    -- for k, v&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- factory()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function faculty( adjust )&lt;br /&gt;
    -- Test template arg for boolean&lt;br /&gt;
    --     adjust  -- string or nil&lt;br /&gt;
    -- Returns boolean&lt;br /&gt;
    local s = type( adjust )&lt;br /&gt;
    local r&lt;br /&gt;
    if s == &amp;quot;string&amp;quot; then&lt;br /&gt;
        r = mw.text.trim( adjust )&lt;br /&gt;
        r = ( r ~= &amp;quot;&amp;quot;  and  r ~= &amp;quot;0&amp;quot; )&lt;br /&gt;
    elseif s == &amp;quot;boolean&amp;quot; then&lt;br /&gt;
        r = adjust&lt;br /&gt;
    else&lt;br /&gt;
        r = false&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- faculty()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function failure( assigned, about )&lt;br /&gt;
    -- Add one message to Errors&lt;br /&gt;
    --     assigned  -- string, with shortcut page name&lt;br /&gt;
    --     about     -- string, with error keyword&lt;br /&gt;
    if type( Errors ) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
        Errors = { }&lt;br /&gt;
    end&lt;br /&gt;
    Errors[ assigned ] = about&lt;br /&gt;
end -- failure()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function fair( above )&lt;br /&gt;
    -- Convert shortcut list namespaces into talk pages&lt;br /&gt;
    --     alert  -- string, with shortcuts&lt;br /&gt;
    -- Returns converted shortcuts&lt;br /&gt;
    local r = &amp;quot; &amp;quot; .. above&lt;br /&gt;
    if type( Config.talks ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
        local seek, shift&lt;br /&gt;
        for k, v in pairs( Config.talks ) do&lt;br /&gt;
            seek  = string.format( &amp;quot;(%%A?)(%s):&amp;quot;, k )&lt;br /&gt;
            shift = string.format( &amp;quot;%%1%s:&amp;quot;, v )&lt;br /&gt;
            r = r:gsub( seek, shift )&lt;br /&gt;
        end    -- for k, v&lt;br /&gt;
    end&lt;br /&gt;
    return mw.text.trim( r )&lt;br /&gt;
end -- fair()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function fallback( access, alt )&lt;br /&gt;
    -- Retrieve message text&lt;br /&gt;
    --     access  -- string, with message ID&lt;br /&gt;
    --     alt     -- string, with plain message, if no access&lt;br /&gt;
    -- Returns string, with any message&lt;br /&gt;
    local r = Config[ access ]&lt;br /&gt;
    if type( r ) ~= &amp;quot;string&amp;quot; then&lt;br /&gt;
        r = alt  or  &amp;quot;***** UNKNOWN MESSAGE &amp;quot; .. access .. &amp;quot; *****&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- fallback()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function fatal( alert )&lt;br /&gt;
    -- Format disaster message with class=&amp;quot;error&amp;quot; and put into category&lt;br /&gt;
    --     alert   -- string, with message, or other data&lt;br /&gt;
    -- Returns message string with markup&lt;br /&gt;
    local elem = mw.html.create( &amp;quot;span&amp;quot; )&lt;br /&gt;
                        :addClass( &amp;quot;error&amp;quot; )&lt;br /&gt;
    local ecat = mw.message.new( &amp;quot;Scribunto-common-error-category&amp;quot; )&lt;br /&gt;
    local r    = type( alert )&lt;br /&gt;
    if r == &amp;quot;string&amp;quot; then&lt;br /&gt;
        r = alert&lt;br /&gt;
    else&lt;br /&gt;
        r = &amp;quot;???? &amp;quot; .. r&lt;br /&gt;
    end&lt;br /&gt;
    elem:wikitext( string.format( &amp;quot;FATAL LUA ERROR %s&amp;quot;, r ) )&lt;br /&gt;
    r = tostring( elem )&lt;br /&gt;
    if not ecat:isBlank() then&lt;br /&gt;
        ecat = string.format( &amp;quot;%s[[Category:%s]]&amp;quot;, r, ecat:plain() )&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- fatal()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function fault( alert, absent )&lt;br /&gt;
    -- Format message with class=&amp;quot;error&amp;quot;; add Config (category etc.)&lt;br /&gt;
    --     alert   -- string, with message&lt;br /&gt;
    --     absent  -- boolean, hide message, trigger category&lt;br /&gt;
    -- Returns message with markup&lt;br /&gt;
    local e = mw.html.create( &amp;quot;span&amp;quot; )&lt;br /&gt;
                     :addClass( &amp;quot;error&amp;quot; )&lt;br /&gt;
                     :wikitext( alert or &amp;quot;???&amp;quot; )&lt;br /&gt;
    local r = tostring( e )&lt;br /&gt;
    if absent  and  type( Config ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
        if type( Config.suppress ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
            facilitated( &amp;quot;suppress&amp;quot; )&lt;br /&gt;
            r = string.format( Config.suppress, r )&lt;br /&gt;
        end&lt;br /&gt;
        if type( Config.scream ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
            r = string.format( &amp;quot;%s[[Category:%s]]&amp;quot;, r, Config.scream )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- fault()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function fiat( ahead, after )&lt;br /&gt;
    -- Format table row&lt;br /&gt;
    --     ahead  -- string, with first cell&lt;br /&gt;
    --     after  -- string or false, with second cell&lt;br /&gt;
    -- Returns table row markup&lt;br /&gt;
    local r = string.format( &amp;quot;\n|-\n|%s&amp;quot;, ahead )&lt;br /&gt;
    if after then&lt;br /&gt;
        r = string.format( &amp;quot;%s||%s&amp;quot;, r, after )&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- fiat()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function first( a1, a2 )&lt;br /&gt;
    -- Compare a1 with a2 in reverse title order&lt;br /&gt;
    --     a1  -- table, with assignment&lt;br /&gt;
    --     a2  -- table, with assignment&lt;br /&gt;
    -- Returns true if a1 &amp;lt; a2&lt;br /&gt;
    local r&lt;br /&gt;
    if  a1.shortcut == a2.shortcut then&lt;br /&gt;
        r = ( string.upper( a1.shift )  &amp;gt;  string.upper( a2.shift ) )&lt;br /&gt;
    elseif a1.sort == a2.sort then&lt;br /&gt;
        r = ( a1.nsn &amp;gt; a2.nsn )&lt;br /&gt;
    else&lt;br /&gt;
        r = ( a1.sort &amp;gt; a2.sort )&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- first()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function flag( alone, achieved )&lt;br /&gt;
    -- Analyze one shortcut&lt;br /&gt;
    --     alone     -- string, with shortcut page name&lt;br /&gt;
    --     achieved  -- table, with title objects; will be extended&lt;br /&gt;
    -- Adds error message to collection&lt;br /&gt;
    local page = mw.title.new( alone )&lt;br /&gt;
    if page.exists then&lt;br /&gt;
        if page.isRedirect then&lt;br /&gt;
            local story = page:getContent()&lt;br /&gt;
            local shift = story:match( &amp;quot;^#[^%[]+%[%[([^%]\n]+)%]%]&amp;quot; )&lt;br /&gt;
            local redirect&lt;br /&gt;
            if not shift  or&lt;br /&gt;
               shift:match( &amp;quot;%%%x%x&amp;quot; ) then&lt;br /&gt;
                redirect = false&lt;br /&gt;
            else&lt;br /&gt;
                redirect = mw.title.new( shift )&lt;br /&gt;
            end&lt;br /&gt;
            if not redirect then&lt;br /&gt;
                failure( alone,&lt;br /&gt;
                         fallback( &amp;quot;sayBadLink&amp;quot;, &amp;quot;bad link encoding&amp;quot; ) )&lt;br /&gt;
            elseif mw.title.equals( Current.page, redirect ) then&lt;br /&gt;
                for k, v in pairs( achieved ) do&lt;br /&gt;
                    if mw.title.equals( page, v ) then&lt;br /&gt;
                        failure( alone,&lt;br /&gt;
                                 fallback( &amp;quot;sayDuplicated&amp;quot;,&lt;br /&gt;
                                           &amp;quot;duplicated&amp;quot; ) )&lt;br /&gt;
                        page = false&lt;br /&gt;
                        break    -- for k, v&lt;br /&gt;
                    end&lt;br /&gt;
                end    -- for k, v&lt;br /&gt;
                if page then&lt;br /&gt;
                    table.insert( achieved, page )&lt;br /&gt;
                end&lt;br /&gt;
                if Current.nsns == Current.nsn&lt;br /&gt;
                   and  not Current.leave&lt;br /&gt;
                   and  Config.signature&lt;br /&gt;
                   and  not story:find( Config.signature, 15 ) then&lt;br /&gt;
                    failure( alone,&lt;br /&gt;
                             fallback( &amp;quot;signal&amp;quot;,&lt;br /&gt;
                                       &amp;quot;.signature (category) missing&amp;quot; )&lt;br /&gt;
                           )&lt;br /&gt;
                end&lt;br /&gt;
            else&lt;br /&gt;
                failure( alone,&lt;br /&gt;
                         fallback( &amp;quot;sayTarget&amp;quot;, &amp;quot;wrong target&amp;quot; ) )&lt;br /&gt;
            end&lt;br /&gt;
        else&lt;br /&gt;
            failure( alone,  fallback( &amp;quot;sayRegular&amp;quot;, &amp;quot;regular page&amp;quot; ) )&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        failure( alone,  fallback( &amp;quot;sayMissing&amp;quot;, &amp;quot;missing&amp;quot; ) )&lt;br /&gt;
    end&lt;br /&gt;
end -- flag()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function flash( account, alone )&lt;br /&gt;
    -- Create all item table body with two columns; shortcut and target&lt;br /&gt;
    --     account   -- string, with module name&lt;br /&gt;
    --     alone     -- number or false, with namespace limitation&lt;br /&gt;
    -- Returns table rows until end, terminate table and provide totals&lt;br /&gt;
    local r = &amp;quot;\n|}&amp;quot;&lt;br /&gt;
    local collect = { }&lt;br /&gt;
    local n, previous&lt;br /&gt;
    if type( alone ) == &amp;quot;number&amp;quot; then&lt;br /&gt;
        n = factory( account, alone, collect )&lt;br /&gt;
    elseif type( Config.rooms ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
        n = 0&lt;br /&gt;
        for k, v in pairs( Config.rooms ) do&lt;br /&gt;
            n = n + factory( account, v, collect )&lt;br /&gt;
        end    -- for k, v&lt;br /&gt;
    else&lt;br /&gt;
        r       = r .. &amp;quot;&amp;#039;Config.rooms&amp;#039; not found&amp;quot;&lt;br /&gt;
        collect = false&lt;br /&gt;
    end&lt;br /&gt;
    if collect then&lt;br /&gt;
        local second, shortcut&lt;br /&gt;
        if not Sort then&lt;br /&gt;
            local l, t = pcall( require, &amp;quot;Module:Sort&amp;quot; )&lt;br /&gt;
            if type( t ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                Sort = t.Sort()&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        table.sort( collect, first )&lt;br /&gt;
        for k, v in pairs( collect ) do&lt;br /&gt;
            shortcut = string.format( &amp;quot;[[%s]]&amp;quot;, v.shortcut )&lt;br /&gt;
            second   = string.format( &amp;quot;[[:%s]]&amp;quot;, v.shift )&lt;br /&gt;
            if v.shortcut == previous then&lt;br /&gt;
                failure( previous,&lt;br /&gt;
                         fallback( &amp;quot;sayDuplicated&amp;quot;, &amp;quot;duplicated&amp;quot; ) )&lt;br /&gt;
            end&lt;br /&gt;
            previous = v.shortcut&lt;br /&gt;
            r = fiat( shortcut, second ) .. r&lt;br /&gt;
        end    -- for k, v&lt;br /&gt;
    end&lt;br /&gt;
    r = string.format( &amp;quot;%s\n%d/%d&amp;quot;, r, #collect, n )&lt;br /&gt;
    return r&lt;br /&gt;
end -- flash()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function folder( arglist )&lt;br /&gt;
    -- Present table rows&lt;br /&gt;
    --     arglist  -- table, with parameters&lt;br /&gt;
    --         .targets  -- table sequence, target pages specifications&lt;br /&gt;
    --         .space    -- string or nil, namespace of all target pages&lt;br /&gt;
    --         .story    -- string or nil, append to target page link&lt;br /&gt;
    --         .suffix   -- string or nil, append to shortcut list&lt;br /&gt;
    -- Returns table row markup&lt;br /&gt;
    local n, s, space, t, targets&lt;br /&gt;
    local r = false&lt;br /&gt;
    if type( arglist.targets ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
        targets = arglist.targets&lt;br /&gt;
        n       = #targets&lt;br /&gt;
    else&lt;br /&gt;
        n = 0&lt;br /&gt;
    end&lt;br /&gt;
    if n == 0 then&lt;br /&gt;
        r = fallback( &amp;quot;sayNoPage&amp;quot;, &amp;quot;No target page&amp;quot; )&lt;br /&gt;
    else&lt;br /&gt;
        if type( arglist.space ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
            space = mw.text.trim( arglist.space )&lt;br /&gt;
            if space == &amp;quot;&amp;quot; then&lt;br /&gt;
                space = false&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        if not space then&lt;br /&gt;
            if n == 1 then&lt;br /&gt;
                space, s     = targets[ 1 ]:match( &amp;quot;^([^:]*):(.+)$&amp;quot; )&lt;br /&gt;
                targets[ 1 ] = s&lt;br /&gt;
                space        = mw.text.trim( space )&lt;br /&gt;
                if space == &amp;quot;&amp;quot; then&lt;br /&gt;
                    space = false&lt;br /&gt;
                end&lt;br /&gt;
            else&lt;br /&gt;
                r = fallback( &amp;quot;sayNoNamespace&amp;quot;, &amp;quot;No target namespace&amp;quot; )&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        if not r then&lt;br /&gt;
            local o, nsn&lt;br /&gt;
            if space then&lt;br /&gt;
                o = mw.site.namespaces[ space ]&lt;br /&gt;
            end&lt;br /&gt;
            if o then&lt;br /&gt;
                nsn   = o.id&lt;br /&gt;
                space = string.format( &amp;quot;:%s:&amp;quot;, o.name )&lt;br /&gt;
            else&lt;br /&gt;
                nsn   = 0&lt;br /&gt;
                space = &amp;quot;:&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
            if type( Config.rooms ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                for k, v in pairs( Config.rooms ) do&lt;br /&gt;
                    if v == nsn then&lt;br /&gt;
                        local l&lt;br /&gt;
                        s = string.format( &amp;quot;%s/%d&amp;quot;, arglist.suite, nsn )&lt;br /&gt;
                        l, t = pcall( mw.loadData, s )&lt;br /&gt;
                        break    -- for k, v&lt;br /&gt;
                    end&lt;br /&gt;
                end    -- for k, v&lt;br /&gt;
            end&lt;br /&gt;
            if type( t ) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
                r = string.format( &amp;quot;%d (%s) * %s&amp;quot;,&lt;br /&gt;
                                   nsn,&lt;br /&gt;
                                   space,&lt;br /&gt;
                                   fallback( &amp;quot;sayNamespaceOff&amp;quot;,&lt;br /&gt;
                                             &amp;quot;Namespace not configured&amp;quot; )&lt;br /&gt;
                                 )&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if r then&lt;br /&gt;
        r = string.format( &amp;quot;\n|-\n|%s&amp;quot;,  fault( r, false ) )&lt;br /&gt;
    else&lt;br /&gt;
        local shortcuts, story, suffix&lt;br /&gt;
        if type( arglist.story ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
            story = arglist.story&lt;br /&gt;
        end&lt;br /&gt;
        if type( arglist.suffix ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
            suffix = arglist.suffix&lt;br /&gt;
        end&lt;br /&gt;
        r = &amp;quot;&amp;quot;&lt;br /&gt;
        for i = 1, n do&lt;br /&gt;
            s         = mw.text.trim( targets[ i ] )&lt;br /&gt;
            shortcuts = t[ s ]&lt;br /&gt;
            s         = string.format( &amp;quot;[[%s%s]]&amp;quot;, space, s )&lt;br /&gt;
            if story then&lt;br /&gt;
                s = s .. story&lt;br /&gt;
            end&lt;br /&gt;
            if type( shortcuts ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
                if shortcuts:sub( 1, 2 ) ~= &amp;quot;[[&amp;quot; then&lt;br /&gt;
                    local got = faces( face( shortcuts ) )&lt;br /&gt;
                    shortcuts = &amp;quot;&amp;quot;&lt;br /&gt;
                    for k, v in pairs( got ) do&lt;br /&gt;
                        shortcuts = string.format( &amp;quot;%s, [[%s]]&amp;quot;,&lt;br /&gt;
                                                   shortcuts, v )&lt;br /&gt;
                    end    -- for k, v&lt;br /&gt;
                    shortcuts = shortcuts:sub( 3 )&lt;br /&gt;
                end&lt;br /&gt;
                if suffix then&lt;br /&gt;
                    shortcuts = shortcuts .. suffix&lt;br /&gt;
                end&lt;br /&gt;
            else&lt;br /&gt;
                shortcuts = fault( fallback( &amp;quot;sayUnregistered&amp;quot;,&lt;br /&gt;
                                             &amp;quot;no shortcuts registered&amp;quot; ),&lt;br /&gt;
                                   false )&lt;br /&gt;
            end&lt;br /&gt;
            r = r .. fiat( s, shortcuts )&lt;br /&gt;
        end -- for i&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- folder()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function follow( arglist )&lt;br /&gt;
    -- Analyze list of shortcuts in single page context&lt;br /&gt;
    --     arglist  -- table, with parameters&lt;br /&gt;
    --         .shortcuts  -- string, comma separated list of shortcuts&lt;br /&gt;
    --         .leave      -- true, if dummy entry&lt;br /&gt;
    -- Throws error with message, else returns string with text&lt;br /&gt;
    local pages     = { }&lt;br /&gt;
    local shortcuts = face( arglist.shortcuts )&lt;br /&gt;
    local style     = Config.style&lt;br /&gt;
    local got, r&lt;br /&gt;
    if Config.show then&lt;br /&gt;
        facilitated( &amp;quot;show&amp;quot; )&lt;br /&gt;
        r = string.format( Config.show, shortcuts )&lt;br /&gt;
    end&lt;br /&gt;
    if Current.style  and  Config[ Current.style ] then&lt;br /&gt;
        style = Config[ Current.style ]&lt;br /&gt;
    elseif Current.rule then&lt;br /&gt;
        got = type( Current.rule.styling )&lt;br /&gt;
        if got == &amp;quot;boolean&amp;quot; then&lt;br /&gt;
            style = false&lt;br /&gt;
        elseif got == &amp;quot;string&amp;quot; then&lt;br /&gt;
            style = Config[ Current.rule.styling ]&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if style then&lt;br /&gt;
        if not Config.light then&lt;br /&gt;
            local s&lt;br /&gt;
            facilitated( &amp;quot;style&amp;quot; )&lt;br /&gt;
            if style:find( &amp;quot;.sub.&amp;quot;, 8, true ) then&lt;br /&gt;
                style = style:gsub( &amp;quot;%.sub%.&amp;quot;, &amp;quot;-sub&amp;quot; )&lt;br /&gt;
            end&lt;br /&gt;
            if style:find( &amp;quot;-shortcut:&amp;quot;, 16, true ) then&lt;br /&gt;
                if Current.page.isSubpage then&lt;br /&gt;
                    s = &amp;quot;%1line-height: 0; top: -2.5em%2&amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                    s = &amp;quot;%1top: -1em%2&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
                style = style:gsub( &amp;quot;([; &amp;#039;])%-shortcut:%s*top([; &amp;#039;])&amp;quot;,&lt;br /&gt;
                                    s )&lt;br /&gt;
                s = &amp;quot;%sdata-shortcut-clear-right=&amp;#039;1&amp;#039;&amp;quot;&lt;br /&gt;
                if style:find( s ) then&lt;br /&gt;
                    e = mw.html.create( &amp;quot;div&amp;quot; )&lt;br /&gt;
                    e:css( { [&amp;quot;clear&amp;quot;]  = &amp;quot;right&amp;quot;,&lt;br /&gt;
                             [&amp;quot;height&amp;quot;] = &amp;quot;0&amp;quot; } )&lt;br /&gt;
                    style = style:gsub( s, &amp;quot;&amp;quot; ) .. tostring( e )&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            r = string.format( style, r )&lt;br /&gt;
            if r:find( &amp;quot;###&amp;quot;, 16, true ) then&lt;br /&gt;
                local k = shortcuts:find( &amp;quot;,&amp;quot;, 3, true )&lt;br /&gt;
                s = shortcuts&lt;br /&gt;
                if k then&lt;br /&gt;
                    s = s:sub( 1,  k - 1 )&lt;br /&gt;
                end&lt;br /&gt;
                r = r:gsub( &amp;quot;###&amp;quot;, s, 1 )&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        r = &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    got = shortcuts:gsub( &amp;quot;&amp;lt;s&amp;gt;[^&amp;lt;]+&amp;lt;/s&amp;gt;&amp;quot;, &amp;quot;&amp;quot; )&lt;br /&gt;
                   :gsub( &amp;quot;&amp;lt;strike&amp;gt;[^&amp;lt;]+&amp;lt;/strike&amp;gt;&amp;quot;, &amp;quot;&amp;quot; )&lt;br /&gt;
    got = faces( got )&lt;br /&gt;
    for k, v in pairs( got ) do&lt;br /&gt;
        if not arglist.leave then&lt;br /&gt;
            flag( v, pages )&lt;br /&gt;
        end&lt;br /&gt;
    end    -- for k, v&lt;br /&gt;
    if Errors then&lt;br /&gt;
        local s = &amp;quot;Shortcuts * &amp;quot;&lt;br /&gt;
        local t&lt;br /&gt;
        for k, v in pairs( Errors ) do&lt;br /&gt;
            t = mw.title.new( k )&lt;br /&gt;
            s = string.format( &amp;quot;%s &amp;lt;u&amp;gt;[%s %s]&amp;lt;/u&amp;gt;:&amp;amp;#160;%s&amp;quot;,&lt;br /&gt;
                               s,&lt;br /&gt;
                               t:fullUrl( { redirect = &amp;quot;no&amp;quot; } ),&lt;br /&gt;
                               k,&lt;br /&gt;
                               v )&lt;br /&gt;
        end    -- for k, v&lt;br /&gt;
        r = r .. fault( s, true )&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- follow()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function forward( args )&lt;br /&gt;
    -- Perform task&lt;br /&gt;
    --     args  -- table, with parameters&lt;br /&gt;
    --         .self       -- string, target page&lt;br /&gt;
    --         .shortcuts  -- string, comma separated list of shortcuts&lt;br /&gt;
    --         .style      -- string, particular style ID&lt;br /&gt;
    --         .loose      -- boolean, ignore undefined shortcuts&lt;br /&gt;
    -- Throws error with message, else returns string with text&lt;br /&gt;
    local l, t, sub&lt;br /&gt;
    local lucky = false&lt;br /&gt;
    local r     = false&lt;br /&gt;
    if type( args.suite ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
        sub = args.suite .. &amp;quot;/config&amp;quot;&lt;br /&gt;
        l, t = pcall( mw.loadData, sub )&lt;br /&gt;
        if type( t ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
            Config = t&lt;br /&gt;
        else&lt;br /&gt;
            r = string.format( &amp;quot;&amp;#039;%s&amp;#039; invalid&amp;quot;, sub )&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        r = &amp;quot;bad .suite&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if Config then&lt;br /&gt;
        local leave = false&lt;br /&gt;
        if args.self then&lt;br /&gt;
            Current.self = args.self&lt;br /&gt;
            Current.page = mw.title.new( Current.self )&lt;br /&gt;
            if not Current.page.exists then&lt;br /&gt;
                Current.page = false&lt;br /&gt;
                r            = string.format( &amp;quot;&amp;#039;%s&amp;#039; not found&amp;quot;,&lt;br /&gt;
                                              Current.self )&lt;br /&gt;
            end&lt;br /&gt;
        elseif args.service == &amp;quot;trows&amp;quot; then&lt;br /&gt;
            lucky = true&lt;br /&gt;
        elseif args.service == &amp;quot;total&amp;quot; then&lt;br /&gt;
            Current.page = false&lt;br /&gt;
            lucky        = true&lt;br /&gt;
        else&lt;br /&gt;
            Current.page = mw.title.getCurrentTitle()&lt;br /&gt;
            Current.self = Current.page.prefixedText&lt;br /&gt;
        end&lt;br /&gt;
        if Current.page then&lt;br /&gt;
            Current.nsn = Current.page.namespace&lt;br /&gt;
            if Current.nsn &amp;lt; 0 then&lt;br /&gt;
                -- Special:Booksources&lt;br /&gt;
                leave = true&lt;br /&gt;
                lucky = true&lt;br /&gt;
            else&lt;br /&gt;
                if Current.nsn % 2 == 0 then&lt;br /&gt;
                    Current.nsns = Current.nsn&lt;br /&gt;
                    Current.nsnt = Current.nsn + 1&lt;br /&gt;
                else&lt;br /&gt;
                    Current.nsnt = Current.nsn&lt;br /&gt;
                    Current.nsns = Current.nsn - 1&lt;br /&gt;
                end&lt;br /&gt;
                t = false&lt;br /&gt;
                if type( Config.rooms ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                    for k, v in pairs( Config.rooms ) do&lt;br /&gt;
                        if v == Current.nsns then&lt;br /&gt;
                            sub  = string.format( &amp;quot;%s/%d&amp;quot;,&lt;br /&gt;
                                                  args.suite, v )&lt;br /&gt;
                            l, t = pcall( mw.loadData, sub )&lt;br /&gt;
                            break    -- for k, v&lt;br /&gt;
                        end&lt;br /&gt;
                    end    -- for k, v&lt;br /&gt;
                end&lt;br /&gt;
                if args.service == &amp;quot;template&amp;quot; then&lt;br /&gt;
                    if type( Config.rules ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                        local rules = Config.rules[ Current.nsn ]&lt;br /&gt;
                        if type( rules ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                            local seek = Current.page.text&lt;br /&gt;
                            local scope&lt;br /&gt;
                            for k, v in pairs( rules ) do&lt;br /&gt;
                                if type( v ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                                    if type( v.sub ) ~= &amp;quot;string&amp;quot;&lt;br /&gt;
                                       or mw.ustring.match( seek,&lt;br /&gt;
                                                            v.sub ) then&lt;br /&gt;
                                        Current.rule.styling = v.styling&lt;br /&gt;
                                        Current.rule.locally = v.locally&lt;br /&gt;
                                    end&lt;br /&gt;
                                end&lt;br /&gt;
                            end    -- for k, v&lt;br /&gt;
                        end&lt;br /&gt;
                    end&lt;br /&gt;
                    if type( t ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                        sub = Current.page.text&lt;br /&gt;
                        if type( t[ sub ] ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
                            if args.shortcuts  and&lt;br /&gt;
                               not Config.locally then&lt;br /&gt;
                                args.shortcuts = false&lt;br /&gt;
                                r              = fallback( &amp;quot;sayNoLocals&amp;quot;,&lt;br /&gt;
                                                   &amp;quot;&amp;#039;1=&amp;#039; not permitted&amp;quot; )&lt;br /&gt;
                            else&lt;br /&gt;
                                args.shortcuts = t[ sub ]&lt;br /&gt;
                                if Current.nsn == Current.nsnt then&lt;br /&gt;
                                    args.shortcuts&lt;br /&gt;
                                                 = fair( args.shortcuts )&lt;br /&gt;
                                end&lt;br /&gt;
                            end&lt;br /&gt;
                        elseif Current.rule.locally then&lt;br /&gt;
                            args.shortcuts = false&lt;br /&gt;
                        end&lt;br /&gt;
                    elseif Current.rule.locally then&lt;br /&gt;
                        args.shortcuts = false&lt;br /&gt;
                    end&lt;br /&gt;
                    if type( args.shortcuts ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
                        local suitable  = Config.patternSuitable or &amp;quot;&amp;quot;&lt;br /&gt;
                        local syntactic = &amp;quot;[_#%{%}|]&amp;quot;&lt;br /&gt;
                        suitable       = string.format( &amp;quot;^[ -~%s]+$&amp;quot;,&lt;br /&gt;
                                                        suitable )&lt;br /&gt;
                        args.shortcuts = mw.text.trim( args.shortcuts )&lt;br /&gt;
                        if args.shortcuts == &amp;quot;&amp;quot; then&lt;br /&gt;
                            r = fallback( &amp;quot;sayNoShortcuts&amp;quot;,&lt;br /&gt;
                                          &amp;quot;no shortcuts&amp;quot; )&lt;br /&gt;
                        elseif Current.leave  and&lt;br /&gt;
                               not args.shortcuts:find( &amp;quot;/&amp;quot; ) then&lt;br /&gt;
                            leave = true&lt;br /&gt;
                        elseif mw.ustring.match( args.shortcuts,&lt;br /&gt;
                                                 suitable )  and&lt;br /&gt;
                               not args.shortcuts:match( syntactic ) then&lt;br /&gt;
                            lucky = true&lt;br /&gt;
                        else&lt;br /&gt;
                            r = fallback( &amp;quot;sayInvalidChar&amp;quot;,&lt;br /&gt;
                                      &amp;quot;shortcut with invalid character&amp;quot; )&lt;br /&gt;
                        end&lt;br /&gt;
                    elseif Current.page.prefixedText == Config.skip then&lt;br /&gt;
                        args.shortcuts = &amp;quot;NS:PT&amp;quot;&lt;br /&gt;
                        args.leave     = true&lt;br /&gt;
                        lucky          = true&lt;br /&gt;
                    elseif args.loose then&lt;br /&gt;
                        leave = true&lt;br /&gt;
                    elseif Config.locally then&lt;br /&gt;
                        r = fallback( &amp;quot;sayUnknown&amp;quot;,&lt;br /&gt;
                                      &amp;quot;Shortcuts template:&amp;quot;&lt;br /&gt;
                                      .. &amp;quot; page not registered,&amp;quot;&lt;br /&gt;
                                      .. &amp;quot; &amp;#039;1=&amp;#039; missing&amp;quot; )&lt;br /&gt;
                    end&lt;br /&gt;
                    if not lucky  and  Current.rule.locally then&lt;br /&gt;
                        lucky = true&lt;br /&gt;
                        leave = true&lt;br /&gt;
                    end&lt;br /&gt;
                elseif args.service ~= &amp;quot;trows&amp;quot;  and&lt;br /&gt;
                       args.service ~= &amp;quot;total&amp;quot; then&lt;br /&gt;
                    r = &amp;quot;bad .service&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        if lucky then&lt;br /&gt;
            if leave then&lt;br /&gt;
                r = &amp;quot;&amp;quot;   -- NOOP&lt;br /&gt;
            elseif args.service == &amp;quot;template&amp;quot; then&lt;br /&gt;
                Current.style  = args.style&lt;br /&gt;
                r = follow( args )&lt;br /&gt;
            elseif args.service == &amp;quot;trows&amp;quot; then&lt;br /&gt;
                r = folder( args )&lt;br /&gt;
            elseif args.service == &amp;quot;total&amp;quot; then&lt;br /&gt;
                r = flash( args.suite, args.nsn )&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if not lucky and r then&lt;br /&gt;
        r = fault( r, true )&lt;br /&gt;
        if args.service == &amp;quot;trows&amp;quot; then&lt;br /&gt;
            r = fiat( r, false )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- forward()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function framed( frame, action )&lt;br /&gt;
    -- #invoke call in template environment&lt;br /&gt;
    --     action  -- string, with keyword&lt;br /&gt;
    -- Returns markup&lt;br /&gt;
    local lucky, r&lt;br /&gt;
    local params = { service = action,&lt;br /&gt;
                     suite   = frame:getTitle() }&lt;br /&gt;
    local pars   = frame:getParent().args&lt;br /&gt;
    if params.service == &amp;quot;template&amp;quot; then&lt;br /&gt;
        params.loose     = faculty( pars.loose )&lt;br /&gt;
        params.shortcuts = pars[ 1 ]&lt;br /&gt;
        if faculty( pars.light )  and&lt;br /&gt;
           params.light  and&lt;br /&gt;
           frame.args.shortcut then&lt;br /&gt;
            params.shortcuts = frame.args.shortcut&lt;br /&gt;
        end&lt;br /&gt;
        if params.shortcuts then&lt;br /&gt;
            params.shortcuts = mw.text.trim( params.shortcuts )&lt;br /&gt;
            if params.shortcuts == &amp;quot;&amp;quot; then&lt;br /&gt;
                params.shortcuts = false&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        params.style = pars.style&lt;br /&gt;
    elseif params.service == &amp;quot;trows&amp;quot; then&lt;br /&gt;
        local k, v, s&lt;br /&gt;
        local got = { }&lt;br /&gt;
        for k, v in pairs( pars ) do&lt;br /&gt;
            if type( k ) == &amp;quot;number&amp;quot; then&lt;br /&gt;
                s = mw.text.trim( v )&lt;br /&gt;
                if s ~= &amp;quot;&amp;quot; then&lt;br /&gt;
                    table.insert( got, s )&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end    -- for k, v&lt;br /&gt;
        if #got &amp;gt; 0 then&lt;br /&gt;
            params.targets = got&lt;br /&gt;
        end&lt;br /&gt;
        params.space  = pars.space&lt;br /&gt;
        params.story  = pars.story&lt;br /&gt;
        params.suffix = pars.suffix&lt;br /&gt;
    elseif params.service == &amp;quot;total&amp;quot; then&lt;br /&gt;
        params.nsn = pars[ 1 ]&lt;br /&gt;
        if params.nsn  and&lt;br /&gt;
           params.nsn:match( &amp;quot;^(%d+)$&amp;quot; ) then&lt;br /&gt;
            params.nsn = tonumber( params.nsn )&lt;br /&gt;
        else&lt;br /&gt;
            params.nsn = false&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    lucky, r = pcall( forward, params )&lt;br /&gt;
    if not lucky then&lt;br /&gt;
        r = fatal( r )&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- framed()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Failsafe.failsafe = function ( atleast )&lt;br /&gt;
    -- Retrieve versioning and check for compliance&lt;br /&gt;
    -- Precondition:&lt;br /&gt;
    --     atleast  -- string, with required version or &amp;quot;wikidata&amp;quot; or &amp;quot;~&amp;quot;&lt;br /&gt;
    --                 or false&lt;br /&gt;
    -- Postcondition:&lt;br /&gt;
    --     Returns  string  -- with queried version, also if problem&lt;br /&gt;
    --              false   -- if appropriate&lt;br /&gt;
    local last  = ( atleast == &amp;quot;~&amp;quot; )&lt;br /&gt;
    local since = atleast&lt;br /&gt;
    local r&lt;br /&gt;
    if last  or  since == &amp;quot;wikidata&amp;quot; then&lt;br /&gt;
        local item = Failsafe.item&lt;br /&gt;
        since = false&lt;br /&gt;
        if type( item ) == &amp;quot;number&amp;quot;  and  item &amp;gt; 0 then&lt;br /&gt;
            local entity = mw.wikibase.getEntity( string.format( &amp;quot;Q%d&amp;quot;,&lt;br /&gt;
                                                                 item ) )&lt;br /&gt;
            if type( entity ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                local vsn = entity:formatPropertyValues( &amp;quot;P348&amp;quot; )&lt;br /&gt;
                if type( vsn ) == &amp;quot;table&amp;quot;  and&lt;br /&gt;
                   type( vsn.value ) == &amp;quot;string&amp;quot;  and&lt;br /&gt;
                   vsn.value ~= &amp;quot;&amp;quot; then&lt;br /&gt;
                    if last  and  vsn.value == Failsafe.serial then&lt;br /&gt;
                        r = false&lt;br /&gt;
                    else&lt;br /&gt;
                        r = vsn.value&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if type( r ) == &amp;quot;nil&amp;quot; then&lt;br /&gt;
        if not since  or  since &amp;lt;= Failsafe.serial then&lt;br /&gt;
            r = Failsafe.serial&lt;br /&gt;
        else&lt;br /&gt;
            r = false&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- Failsafe.failsafe()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-- Export&lt;br /&gt;
local p = { }&lt;br /&gt;
&lt;br /&gt;
function p.template( frame )&lt;br /&gt;
    return  framed( frame, &amp;quot;template&amp;quot; )  or  &amp;quot;&amp;quot;&lt;br /&gt;
end -- .template&lt;br /&gt;
&lt;br /&gt;
function p.total( frame )&lt;br /&gt;
    return  framed( frame, &amp;quot;total&amp;quot; )&lt;br /&gt;
end -- .total&lt;br /&gt;
&lt;br /&gt;
function p.trows( frame )&lt;br /&gt;
    return  framed( frame, &amp;quot;trows&amp;quot; )&lt;br /&gt;
end -- .trows&lt;br /&gt;
&lt;br /&gt;
function p.twoletters( frame )&lt;br /&gt;
    return  framed( frame, &amp;quot;twoletters&amp;quot; )&lt;br /&gt;
end -- .twoletters&lt;br /&gt;
&lt;br /&gt;
function p.test( args )&lt;br /&gt;
    -- Debugging&lt;br /&gt;
    --     args  -- table, with arguments; mandatory:&lt;br /&gt;
    --              .suite      -- Module path&lt;br /&gt;
    --              .service    -- action mode, like &amp;quot;template&amp;quot;&lt;br /&gt;
    --              .shortcuts  -- list&lt;br /&gt;
    --              .self       -- (target) page name&lt;br /&gt;
    local lucky, r = pcall( forward, args )&lt;br /&gt;
    return r&lt;br /&gt;
end -- .test()&lt;br /&gt;
&lt;br /&gt;
p.failsafe = function ( frame )&lt;br /&gt;
    -- Versioning interface&lt;br /&gt;
    local s = type( frame )&lt;br /&gt;
    local since&lt;br /&gt;
    if s == &amp;quot;table&amp;quot; then&lt;br /&gt;
        since = frame.args[ 1 ]&lt;br /&gt;
    elseif s == &amp;quot;string&amp;quot; then&lt;br /&gt;
        since = frame&lt;br /&gt;
    end&lt;br /&gt;
    if since then&lt;br /&gt;
        since = mw.text.trim( since )&lt;br /&gt;
        if since == &amp;quot;&amp;quot; then&lt;br /&gt;
            since = false&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return Failsafe.failsafe( since )  or  &amp;quot;&amp;quot;&lt;br /&gt;
end -- .failsafe&lt;br /&gt;
&lt;br /&gt;
p.Shortcuts = function ()&lt;br /&gt;
    -- Module interface&lt;br /&gt;
    return Shortcuts&lt;br /&gt;
end -- .Shortcuts&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>UltimateG4ming</name></author>
	</entry>
</feed>