<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://de.wikijournal.org/w-wiki/index.php?action=history&amp;feed=atom&amp;title=Modul%3AJSONutil</id>
	<title>Modul:JSONutil - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://de.wikijournal.org/w-wiki/index.php?action=history&amp;feed=atom&amp;title=Modul%3AJSONutil"/>
	<link rel="alternate" type="text/html" href="https://de.wikijournal.org/w-wiki/index.php?title=Modul:JSONutil&amp;action=history"/>
	<updated>2026-04-11T18:54:47Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in WikiJournal</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://de.wikijournal.org/w-wiki/index.php?title=Modul:JSONutil&amp;diff=299&amp;oldid=prev</id>
		<title>Philip: 1 Version importiert</title>
		<link rel="alternate" type="text/html" href="https://de.wikijournal.org/w-wiki/index.php?title=Modul:JSONutil&amp;diff=299&amp;oldid=prev"/>
		<updated>2025-02-05T06:57:53Z</updated>

		<summary type="html">&lt;p&gt;1 Version importiert&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;de&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Nächstältere Version&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Version vom 5. Februar 2025, 09:57 Uhr&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&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;!-- diff cache key wikijournal_org-de__:diff:1.41:old-298:rev-299 --&gt;
&lt;/table&gt;</summary>
		<author><name>Philip</name></author>
	</entry>
	<entry>
		<id>https://de.wikijournal.org/w-wiki/index.php?title=Modul:JSONutil&amp;diff=298&amp;oldid=prev</id>
		<title>__de&gt;PerfektesChaos: 2020-11-08</title>
		<link rel="alternate" type="text/html" href="https://de.wikijournal.org/w-wiki/index.php?title=Modul:JSONutil&amp;diff=298&amp;oldid=prev"/>
		<updated>2020-11-23T16:55:56Z</updated>

		<summary type="html">&lt;p&gt;2020-11-08&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local JSONutil = { suite  = &amp;quot;JSONutil&amp;quot;,&lt;br /&gt;
                   serial = &amp;quot;2020-11-08&amp;quot;,&lt;br /&gt;
                   item   = 63869449 }&lt;br /&gt;
--[=[&lt;br /&gt;
preprocess or generate JSON data&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local Failsafe = JSONutil&lt;br /&gt;
JSONutil.Encoder  = { stab   = string.char( 9 ),&lt;br /&gt;
                      sep    = string.char( 10 ),&lt;br /&gt;
                      scream = &amp;quot;@error@JSONencoder@&amp;quot; }&lt;br /&gt;
JSONutil.more = 50    -- length of trailing context&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local Fallback = function ()&lt;br /&gt;
    -- Retrieve current default language code&lt;br /&gt;
    --     Returns  string&lt;br /&gt;
    return mw.language.getContentLanguage():getCode()&lt;br /&gt;
                                           :lower()&lt;br /&gt;
end -- Fallback()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local flat = function ( adjust )&lt;br /&gt;
    -- Clean template argument string&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     adjust  -- string, or not&lt;br /&gt;
    -- Returns:&lt;br /&gt;
    --     string&lt;br /&gt;
    local r&lt;br /&gt;
    if adjust then&lt;br /&gt;
        r = mw.text.trim( mw.text.unstripNoWiki( adjust ) )&lt;br /&gt;
    else&lt;br /&gt;
        r = &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- flat()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local flip = function ( frame )&lt;br /&gt;
    -- Retrieve template argument indent&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     frame  -- object&lt;br /&gt;
    -- Returns:&lt;br /&gt;
    --     number, of indentation level, or not&lt;br /&gt;
    local r&lt;br /&gt;
    if frame.args.indent  and  frame.args.indent:match( &amp;quot;^%d+$&amp;quot; ) then&lt;br /&gt;
        r = tonumber( frame.args.indent )&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- flip()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JSONutil.Encoder.Array = function ( apply, adapt, alert )&lt;br /&gt;
    -- Convert table to JSON Array&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     apply  -- table, with sequence of raw elements, or&lt;br /&gt;
    --               string, with formatted Array, or empty&lt;br /&gt;
    --     adapt  -- string, with requested type, or not&lt;br /&gt;
    --     alert  -- true, if non-numeric elements shall trigger errors&lt;br /&gt;
    -- Returns:&lt;br /&gt;
    --     string, with JSON Array&lt;br /&gt;
    local r = type( apply )&lt;br /&gt;
    if r == &amp;quot;string&amp;quot; then&lt;br /&gt;
        r = mw.text.trim( apply )&lt;br /&gt;
        if r == &amp;quot;&amp;quot; then&lt;br /&gt;
            r = &amp;quot;[]&amp;quot;&lt;br /&gt;
        elseif r:byte( 1, 1 ) ~= 0x5B  or&lt;br /&gt;
               r:byte( -1, -1 ) ~= 0x5D then&lt;br /&gt;
            r = false&lt;br /&gt;
        end&lt;br /&gt;
    elseif r == &amp;quot;table&amp;quot; then&lt;br /&gt;
        local n = 0&lt;br /&gt;
        local strange&lt;br /&gt;
        for k, v in pairs( apply ) do&lt;br /&gt;
            if type( k ) == &amp;quot;number&amp;quot; then&lt;br /&gt;
                if k &amp;gt; n then&lt;br /&gt;
                    n = k&lt;br /&gt;
                end&lt;br /&gt;
            elseif alert then&lt;br /&gt;
                if strange then&lt;br /&gt;
                    strange = strange .. &amp;quot; &amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                    strange = &amp;quot;&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
                strange = strange .. tostring( k )&lt;br /&gt;
            end&lt;br /&gt;
        end -- for k, v&lt;br /&gt;
        if strange then&lt;br /&gt;
            r = string.format( &amp;quot;{ \&amp;quot;%s\&amp;quot;: \&amp;quot;%s\&amp;quot; }&amp;quot;,&lt;br /&gt;
                               JSONutil.Encoder.scream,&lt;br /&gt;
                               JSONutil.Encoder.string( strange ) )&lt;br /&gt;
        elseif n &amp;gt; 0 then&lt;br /&gt;
            local sep   = &amp;quot;&amp;quot;&lt;br /&gt;
            local scope = adapt or &amp;quot;string&amp;quot;&lt;br /&gt;
            local s&lt;br /&gt;
            if type( JSONutil.Encoder[ scope ] ) ~= &amp;quot;function&amp;quot; then&lt;br /&gt;
                scope = &amp;quot;string&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
            r = &amp;quot; ]&amp;quot;&lt;br /&gt;
            for i = n, 1, -1 do&lt;br /&gt;
                s = JSONutil.Encoder[ scope ]( apply[ i ] )&lt;br /&gt;
                r = string.format( &amp;quot;%s%s%s&amp;quot;, s, sep, r )&lt;br /&gt;
                sep = &amp;quot;,\n  &amp;quot;&lt;br /&gt;
            end -- for i = n, 1, -1&lt;br /&gt;
            r = &amp;quot;[ &amp;quot; .. r&lt;br /&gt;
        else&lt;br /&gt;
            r = &amp;quot;[]&amp;quot;&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        r = false&lt;br /&gt;
    end&lt;br /&gt;
    if not r then&lt;br /&gt;
        r = string.format( &amp;quot;[ \&amp;quot;%s * %s\&amp;quot; ]&amp;quot;,&lt;br /&gt;
                           JSONutil.Encoder.scream,&lt;br /&gt;
                           &amp;quot;Bad Array&amp;quot; )&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- JSONutil.Encoder.Array()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JSONutil.Encoder.boolean = function ( apply )&lt;br /&gt;
    -- Convert string to JSON boolean&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     apply  -- string, with value&lt;br /&gt;
    -- Returns:&lt;br /&gt;
    --     boolean as string&lt;br /&gt;
    local r = mw.text.trim( apply )&lt;br /&gt;
    if r == &amp;quot;&amp;quot;  or  r == &amp;quot;null&amp;quot;  or  r == &amp;quot;false&amp;quot;&lt;br /&gt;
       or  r == &amp;quot;0&amp;quot;  or  r == &amp;quot;-&amp;quot; then&lt;br /&gt;
        r = &amp;quot;false&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
        r = &amp;quot;true&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- JSONutil.Encoder.boolean()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JSONutil.Encoder.Component = function ( access, apply,&lt;br /&gt;
                                        adapt, align, alert )&lt;br /&gt;
    -- Create single entry for mapping object&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     access  -- string, with component name&lt;br /&gt;
    --     apply   -- component value&lt;br /&gt;
    --     adapt   -- string, with value type, or not&lt;br /&gt;
    --     align   -- number, of indentation level, or not&lt;br /&gt;
    --     alert   --&lt;br /&gt;
    -- Returns:&lt;br /&gt;
    --     string, with JSON fragment, and comma&lt;br /&gt;
    local v     = apply&lt;br /&gt;
    local types = adapt&lt;br /&gt;
    local indent, liner, scope, sep, sign&lt;br /&gt;
    if type( access ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
        sign = mw.text.trim( access )&lt;br /&gt;
        if sign == &amp;quot;&amp;quot; then&lt;br /&gt;
            sign = false&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if type( types ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
        types = mw.text.split( mw.text.trim( types ),  &amp;quot;%s+&amp;quot; )&lt;br /&gt;
    end&lt;br /&gt;
    if type( types ) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
        types = { }&lt;br /&gt;
        table.insert( types, &amp;quot;string&amp;quot; )&lt;br /&gt;
    end&lt;br /&gt;
    if #types == 1 then&lt;br /&gt;
        scope = types[ 1 ]&lt;br /&gt;
    else&lt;br /&gt;
        for i = 1, #types do&lt;br /&gt;
            if types[ i ] == &amp;quot;boolean&amp;quot; then&lt;br /&gt;
                if v == &amp;quot;1&amp;quot;  or  v == 1  or  v == true then&lt;br /&gt;
                    v = &amp;quot;true&amp;quot;&lt;br /&gt;
                    scope = &amp;quot;boolean&amp;quot;&lt;br /&gt;
                elseif v == &amp;quot;0&amp;quot;  or  v == 0  or  v == false then&lt;br /&gt;
                    v = &amp;quot;false&amp;quot;&lt;br /&gt;
                    scope = &amp;quot;boolean&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
                if scope then&lt;br /&gt;
                    types = { }&lt;br /&gt;
                    break    -- for i&lt;br /&gt;
                else&lt;br /&gt;
                    table.remove( types, i )&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end   -- for i&lt;br /&gt;
        for i = 1, #types do&lt;br /&gt;
            if types[ i ] == &amp;quot;number&amp;quot; then&lt;br /&gt;
                if tonumber( v ) then&lt;br /&gt;
                    v     = tostring( v )&lt;br /&gt;
                    scope = &amp;quot;number&amp;quot;&lt;br /&gt;
                    types = { }&lt;br /&gt;
                    break    -- for i&lt;br /&gt;
                else&lt;br /&gt;
                    table.remove( types, i )&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end    -- for i&lt;br /&gt;
    end&lt;br /&gt;
    scope = scope or &amp;quot;string&amp;quot;&lt;br /&gt;
    if type( JSONutil.Encoder[ scope ] ) ~= &amp;quot;function&amp;quot; then&lt;br /&gt;
        scope = &amp;quot;string&amp;quot;&lt;br /&gt;
    elseif scope == &amp;quot;I18N&amp;quot; then&lt;br /&gt;
        scope = &amp;quot;Polyglott&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if scope == &amp;quot;string&amp;quot; then&lt;br /&gt;
        v = v or &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if type( align ) == &amp;quot;number&amp;quot;  and  align &amp;gt; 0 then&lt;br /&gt;
        indent = math.floor( align )&lt;br /&gt;
        if indent == 0 then&lt;br /&gt;
            indent = false&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if scope == &amp;quot;object&amp;quot;  or  not sign then&lt;br /&gt;
        liner = true&lt;br /&gt;
    elseif scope == &amp;quot;string&amp;quot; then&lt;br /&gt;
        local k = mw.ustring.len( sign ) + mw.ustring.len( v )&lt;br /&gt;
        if k &amp;gt; 60 then&lt;br /&gt;
            liner = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if liner then&lt;br /&gt;
        if indent then&lt;br /&gt;
            sep = &amp;quot;\n&amp;quot; .. string.rep( &amp;quot;  &amp;quot;, indent )&lt;br /&gt;
        else&lt;br /&gt;
            sep = &amp;quot;\n&amp;quot;&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        sep = &amp;quot; &amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if indent then&lt;br /&gt;
        indent = indent + 1&lt;br /&gt;
    end&lt;br /&gt;
    return  string.format( &amp;quot; \&amp;quot;%s\&amp;quot;:%s%s,\n&amp;quot;,&lt;br /&gt;
                           sign or &amp;quot;???&amp;quot;,&lt;br /&gt;
                           sep,&lt;br /&gt;
                           JSONutil.Encoder[ scope ]( v, indent ) )&lt;br /&gt;
end -- JSONutil.Encoder.Component()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JSONutil.Encoder.Hash = function ( apply, adapt, alert )&lt;br /&gt;
    -- Create entries for mapping object&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     apply  -- table, with element value assignments&lt;br /&gt;
    --     adapt  -- table, with value types assignment, or not&lt;br /&gt;
    -- Returns:&lt;br /&gt;
    --     string, with JSON fragment, and comma&lt;br /&gt;
    local r = &amp;quot;&amp;quot;&lt;br /&gt;
    local s&lt;br /&gt;
    for k, v in pairs( apply ) do&lt;br /&gt;
        if type( adapt ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
            s = adapt[ k ]&lt;br /&gt;
        end&lt;br /&gt;
        r = r .. JSONutil.Encoder.Component( tostring( k ), v, s )&lt;br /&gt;
    end -- for k, v&lt;br /&gt;
    return&lt;br /&gt;
end -- JSONutil.Encoder.Hash()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JSONutil.Encoder.I18N = function ( apply, align )&lt;br /&gt;
    -- Convert multilingual string table to JSON&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     apply  -- table, with mapping object&lt;br /&gt;
    --     align  -- number, of indentation level, or not&lt;br /&gt;
    -- Returns:&lt;br /&gt;
    --     string, with JSON object&lt;br /&gt;
    local r = type( apply )&lt;br /&gt;
    if r == &amp;quot;table&amp;quot; then&lt;br /&gt;
        local strange&lt;br /&gt;
        local fault = function ( a )&lt;br /&gt;
                  if strange then&lt;br /&gt;
                      strange = strange .. &amp;quot; *\n &amp;quot;&lt;br /&gt;
                  else&lt;br /&gt;
                      strange = &amp;quot;&amp;quot;&lt;br /&gt;
                  end&lt;br /&gt;
                  strange = strange .. a&lt;br /&gt;
              end&lt;br /&gt;
        local got, sep, indent&lt;br /&gt;
        for k, v in pairs( apply ) do&lt;br /&gt;
            if type( k ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
                k = mw.text.trim( k )&lt;br /&gt;
                if type( v ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
                    v = mw.text.trim( v )&lt;br /&gt;
                    if v == &amp;quot;&amp;quot; then&lt;br /&gt;
                        fault( string.format( &amp;quot;%s %s=&amp;quot;,&lt;br /&gt;
                                              &amp;quot;Empty text&amp;quot;, k ) )&lt;br /&gt;
                    end&lt;br /&gt;
                    if not ( k:match( &amp;quot;%l%l%l?&amp;quot; )  or&lt;br /&gt;
                             k:match( &amp;quot;%l%l%l?-%u%u&amp;quot; )  or&lt;br /&gt;
                             k:match( &amp;quot;%l%l%l?-%u%l%l%l+&amp;quot; ) ) then&lt;br /&gt;
                        fault( string.format( &amp;quot;%s %s=&amp;quot;,&lt;br /&gt;
                                              &amp;quot;Strange language code&amp;quot;,&lt;br /&gt;
                                              k ) )&lt;br /&gt;
                    end&lt;br /&gt;
                else&lt;br /&gt;
                    v = tostring( v )&lt;br /&gt;
                    fault( string.format( &amp;quot;%s %s=%s&amp;quot;,&lt;br /&gt;
                                          &amp;quot;Bad type for text&amp;quot;,&lt;br /&gt;
                                          k,&lt;br /&gt;
                                          type( v ) ) )&lt;br /&gt;
                end&lt;br /&gt;
                got = got  or  { }&lt;br /&gt;
                got[ k ] = v&lt;br /&gt;
            else&lt;br /&gt;
                fault( string.format( &amp;quot;%s %s: %s&amp;quot;,&lt;br /&gt;
                                      &amp;quot;Bad language code type&amp;quot;,&lt;br /&gt;
                                      type( k ),&lt;br /&gt;
                                      tostring( k ) ) )&lt;br /&gt;
            end&lt;br /&gt;
        end -- for k, v&lt;br /&gt;
        if not got then&lt;br /&gt;
            fault( &amp;quot;No language codes&amp;quot; )&lt;br /&gt;
            got = { }&lt;br /&gt;
        end&lt;br /&gt;
        if strange then&lt;br /&gt;
            got[ JSONutil.Encoder.scream ] = strange&lt;br /&gt;
        end&lt;br /&gt;
        r = false&lt;br /&gt;
        if type( align ) == &amp;quot;number&amp;quot;  and  align &amp;gt; 0 then&lt;br /&gt;
            indent = math.floor( align ) &lt;br /&gt;
        else&lt;br /&gt;
            indent = 0&lt;br /&gt;
        end&lt;br /&gt;
        sep = string.rep( &amp;quot;  &amp;quot;,  indent + 1 ) &lt;br /&gt;
        for k, v in pairs( got ) do&lt;br /&gt;
            if r then&lt;br /&gt;
                r = r .. &amp;quot;,\n&amp;quot;&lt;br /&gt;
            else&lt;br /&gt;
                r = &amp;quot;&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
            r = string.format( &amp;quot;%s  %s%s: %s&amp;quot;,&lt;br /&gt;
                               r,&lt;br /&gt;
                               sep,&lt;br /&gt;
                               JSONutil.Encoder.string( k ),&lt;br /&gt;
                               JSONutil.Encoder.string( v ) )&lt;br /&gt;
        end -- for k, v&lt;br /&gt;
        r = string.format( &amp;quot;{\n%s\n%s}&amp;quot;, r, sep )&lt;br /&gt;
    elseif r == &amp;quot;string&amp;quot; then&lt;br /&gt;
        r = JSONutil.Encoder.string( apply )&lt;br /&gt;
    else&lt;br /&gt;
        r = string.format( &amp;quot;{ \&amp;quot;%s\&amp;quot;: \&amp;quot;%s: %s\&amp;quot; }&amp;quot;,&lt;br /&gt;
                           JSONutil.Encoder.scream,&lt;br /&gt;
                           &amp;quot;Bad Lua type&amp;quot;,&lt;br /&gt;
                           r )&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- JSONutil.Encoder.I18N()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JSONutil.Encoder.number = function ( apply )&lt;br /&gt;
    -- Convert string to JSON number&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     apply  -- string, with presumable number&lt;br /&gt;
    -- Returns:&lt;br /&gt;
    --     number, or &amp;quot;NaN&amp;quot;&lt;br /&gt;
    local s = mw.text.trim( apply )&lt;br /&gt;
    JSONutil.Encoder.minus = JSONutil.Encoder.minus  or&lt;br /&gt;
                             mw.ustring.char( 0x2212 )&lt;br /&gt;
    s = s:gsub( JSONutil.Encoder.minus, &amp;quot;-&amp;quot; )&lt;br /&gt;
    return tonumber( s:lower() )  or  &amp;quot;NaN&amp;quot;&lt;br /&gt;
end -- JSONutil.Encoder.number()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JSONutil.Encoder.object = function ( apply, align )&lt;br /&gt;
    -- Create mapping object&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     apply  -- string, with components, may end with comma&lt;br /&gt;
    --     align  -- number, of indentation level, or not&lt;br /&gt;
    -- Returns:&lt;br /&gt;
    --     string, with JSON fragment&lt;br /&gt;
    local story = mw.text.trim( apply )&lt;br /&gt;
    local start = &amp;quot;&amp;quot;&lt;br /&gt;
    if story:sub( -1 ) == &amp;quot;,&amp;quot; then&lt;br /&gt;
        story = story:sub( 1, -2 )&lt;br /&gt;
    end&lt;br /&gt;
    if type( align ) == &amp;quot;number&amp;quot;  and  align &amp;gt; 0 then&lt;br /&gt;
        local indent = math.floor( align )&lt;br /&gt;
        if indent &amp;gt; 0 then&lt;br /&gt;
            start = string.rep( &amp;quot;  &amp;quot;, indent )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return  string.format( &amp;quot;%s{ %s\n%s}&amp;quot;, start, story, start )&lt;br /&gt;
end -- JSONutil.Encoder.object()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JSONutil.Encoder.Polyglott = function ( apply, align )&lt;br /&gt;
    -- Convert string or multilingual string table to JSON&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     apply  -- string, with string or object&lt;br /&gt;
    --     align  -- number, of indentation level, or not&lt;br /&gt;
    -- Returns:&lt;br /&gt;
    --     string&lt;br /&gt;
    local r = type( apply )&lt;br /&gt;
    if r == &amp;quot;string&amp;quot; then&lt;br /&gt;
        r = mw.text.trim( apply )&lt;br /&gt;
        if not r:match( &amp;quot;^{%s*\&amp;quot;&amp;quot; )  or&lt;br /&gt;
           not r:match( &amp;quot;\&amp;quot;%s*}$&amp;quot; ) then&lt;br /&gt;
            r = JSONutil.Encoder.string( r )&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        r = string.format( &amp;quot;{ \&amp;quot;%s\&amp;quot;: \&amp;quot;%s: %s\&amp;quot; }&amp;quot;,&lt;br /&gt;
                           JSONutil.Encoder.scream,&lt;br /&gt;
                           &amp;quot;Bad Lua type&amp;quot;,&lt;br /&gt;
                           r )&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- JSONutil.Encoder.Polyglott()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JSONutil.Encoder.string = function ( apply )&lt;br /&gt;
    -- Convert plain string to strict JSON string&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     apply  -- string, with plain string&lt;br /&gt;
    -- Returns:&lt;br /&gt;
    --     string, with quoted trimmed JSON string&lt;br /&gt;
    return  string.format( &amp;quot;\&amp;quot;%s\&amp;quot;&amp;quot;,&lt;br /&gt;
                           mw.text.trim( apply )&lt;br /&gt;
                                  :gsub( &amp;quot;\\&amp;quot;,  &amp;quot;\\\\&amp;quot; )&lt;br /&gt;
                                  :gsub( &amp;quot;\&amp;quot;&amp;quot;,  &amp;quot;\\\&amp;quot;&amp;quot; )&lt;br /&gt;
                                  :gsub( JSONutil.Encoder.sep,  &amp;quot;\\n&amp;quot; )&lt;br /&gt;
                                  :gsub( JSONutil.Encoder.stab, &amp;quot;\\t&amp;quot; ) )&lt;br /&gt;
end -- JSONutil.Encoder.string()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JSONutil.fair = function ( apply )&lt;br /&gt;
    -- Reduce enhanced JSON data to strict JSON&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     apply  -- string, with enhanced JSON&lt;br /&gt;
    -- Returns:&lt;br /&gt;
    --     1    -- string|nil|false, with error keyword&lt;br /&gt;
    --     2    -- string, with JSON or context&lt;br /&gt;
    local m   = 0&lt;br /&gt;
    local n   = 0&lt;br /&gt;
    local s   = mw.text.trim( apply )&lt;br /&gt;
    local i, j, last, r, scan, sep0, sep1, start, stub, suffix&lt;br /&gt;
    local framework = function ( a )&lt;br /&gt;
                              -- syntax analysis outside strings&lt;br /&gt;
                              local k = 1&lt;br /&gt;
                              local c&lt;br /&gt;
                              while k do&lt;br /&gt;
                                  k = a:find( &amp;quot;[{%[%]}]&amp;quot;, k )&lt;br /&gt;
                                  if k then&lt;br /&gt;
                                      c = a:byte( k, k )&lt;br /&gt;
                                      if c == 0x7B then    -- {&lt;br /&gt;
                                          m = m + 1&lt;br /&gt;
                                      elseif c == 0x7D then    -- }&lt;br /&gt;
                                          m = m - 1&lt;br /&gt;
                                      elseif c == 0x5B then    -- [&lt;br /&gt;
                                          n = n + 1&lt;br /&gt;
                                      else    -- ]&lt;br /&gt;
                                          n = n - 1&lt;br /&gt;
                                      end&lt;br /&gt;
                                      k = k + 1&lt;br /&gt;
                                  end&lt;br /&gt;
                              end   -- while k&lt;br /&gt;
                      end    -- framework()&lt;br /&gt;
    local free = function ( a, at, f )&lt;br /&gt;
                     -- Throws: error if /* is not matched by */&lt;br /&gt;
                     local s = a&lt;br /&gt;
                     local i = s:find( &amp;quot;//&amp;quot;, at, true )&lt;br /&gt;
                     local k = s:find( &amp;quot;/*&amp;quot;, at, true )&lt;br /&gt;
                     if i or k then&lt;br /&gt;
                         local m = s:find( sep0, at )&lt;br /&gt;
                         if i   and   ( not m  or  i &amp;lt; m ) then&lt;br /&gt;
                             k = s:find( &amp;quot;\n&amp;quot;,  i + 2,  true )&lt;br /&gt;
                             if k then&lt;br /&gt;
                                 if i == 1 then&lt;br /&gt;
                                     s = s:sub( k + 1 )&lt;br /&gt;
                                 else&lt;br /&gt;
                                     s = s:sub( 1,  i - 1 )   ..&lt;br /&gt;
                                         s:sub( k + 1 )&lt;br /&gt;
                                 end&lt;br /&gt;
                             elseif i &amp;gt; 1 then&lt;br /&gt;
                                 s = s:sub( 1,  i - 1 )&lt;br /&gt;
                             else&lt;br /&gt;
                                 s = &amp;quot;&amp;quot;&lt;br /&gt;
                             end&lt;br /&gt;
                         elseif k   and   ( not m  or  k &amp;lt; m ) then&lt;br /&gt;
                             i = s:find( &amp;quot;*/&amp;quot;,  k + 2,  true )&lt;br /&gt;
                             if i then&lt;br /&gt;
                                 if k == 1 then&lt;br /&gt;
                                     s = s:sub( i + 2 )&lt;br /&gt;
                                 else&lt;br /&gt;
                                     s = s:sub( 1,  k - 1 )   ..&lt;br /&gt;
                                         s:sub( i + 2 )&lt;br /&gt;
                                 end&lt;br /&gt;
                             else&lt;br /&gt;
                                 error( s:sub( k + 2 ), 0 )&lt;br /&gt;
                             end&lt;br /&gt;
                             i = k&lt;br /&gt;
                         else&lt;br /&gt;
                             i = false&lt;br /&gt;
                         end&lt;br /&gt;
                         if i then&lt;br /&gt;
                             s = mw.text.trim( s )&lt;br /&gt;
                             if s:find( &amp;quot;/&amp;quot;, 1, true ) then&lt;br /&gt;
                                 s = f( s, i, f )&lt;br /&gt;
                             end&lt;br /&gt;
                         end&lt;br /&gt;
                     end&lt;br /&gt;
                     return s&lt;br /&gt;
                 end    -- free()&lt;br /&gt;
    if s:sub( 1, 1 ) == &amp;#039;{&amp;#039; then&lt;br /&gt;
        s    = s:gsub( string.char( 13, 10 ),  JSONutil.Encoder.sep )&lt;br /&gt;
                :gsub( string.char( 13 ),  JSONutil.Encoder.sep )&lt;br /&gt;
        stub = s:gsub( JSONutil.Encoder.sep, &amp;quot;&amp;quot; )&lt;br /&gt;
                :gsub( JSONutil.Encoder.stab, &amp;quot;&amp;quot; )&lt;br /&gt;
        scan = string.char( 0x5B, 0x01, 0x2D, 0x1F, 0x5D )    -- [ \-\ ]&lt;br /&gt;
        j    = stub:find( scan )&lt;br /&gt;
        if j then&lt;br /&gt;
            r = &amp;quot;ControlChar&amp;quot;&lt;br /&gt;
            s = mw.text.trim( s:sub( j + 1 ) )&lt;br /&gt;
            s = mw.ustring.sub( s, 1, JSONutil.more )&lt;br /&gt;
        else&lt;br /&gt;
            i    = true&lt;br /&gt;
            j    = 1&lt;br /&gt;
            last = ( stub:sub( -1 ) == &amp;quot;}&amp;quot; )&lt;br /&gt;
            sep0 = string.char( 0x5B, 0x22, 0x27, 0x5D )    -- [ &amp;quot; &amp;#039; ]&lt;br /&gt;
            sep1 = string.char( 0x5B, 0x5C, 0x22, 0x5D )    -- [ \ &amp;quot; ]&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        r = &amp;quot;Bracket0&amp;quot;&lt;br /&gt;
        s = mw.ustring.sub( s, 1, JSONutil.more )&lt;br /&gt;
    end&lt;br /&gt;
    while i do&lt;br /&gt;
        i, s = pcall( free, s, j, free )&lt;br /&gt;
        if i then&lt;br /&gt;
            i = s:find( sep0, j )&lt;br /&gt;
        else&lt;br /&gt;
            r = &amp;quot;CommentEnd&amp;quot;&lt;br /&gt;
            s = mw.text.trim( s )&lt;br /&gt;
            s = mw.ustring.sub( s, 1, JSONutil.more )&lt;br /&gt;
        end&lt;br /&gt;
        if i then&lt;br /&gt;
            if j == 1 then&lt;br /&gt;
                framework( s:sub( 1, i - 1 ) )&lt;br /&gt;
            end&lt;br /&gt;
            if s:sub( i, i ) == &amp;#039;&amp;quot;&amp;#039; then&lt;br /&gt;
                stub = s:sub( j,  i - 1 )&lt;br /&gt;
                if stub:find( &amp;#039;[^&amp;quot;]*,%s*[%]}]&amp;#039; ) then&lt;br /&gt;
                    r = &amp;quot;CommaEnd&amp;quot;&lt;br /&gt;
                    s = mw.text.trim( stub )&lt;br /&gt;
                    s = mw.ustring.sub( s, 1, JSONutil.more )&lt;br /&gt;
                    i = false&lt;br /&gt;
                    j = false&lt;br /&gt;
                else&lt;br /&gt;
                    if j &amp;gt; 1 then&lt;br /&gt;
                        framework( stub )&lt;br /&gt;
                    end&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
                    j = i&lt;br /&gt;
                end&lt;br /&gt;
                while j do&lt;br /&gt;
                    j = s:find( sep1, j )&lt;br /&gt;
                    if j then&lt;br /&gt;
                        if s:sub( j, j ) == &amp;#039;&amp;quot;&amp;#039; then&lt;br /&gt;
                            start  = s:sub( 1,  i - 1 )&lt;br /&gt;
                            suffix = s:sub( j )&lt;br /&gt;
                            if j &amp;gt; i then&lt;br /&gt;
                                stub = s:sub( i,  j - 1 )&lt;br /&gt;
                                        :gsub( JSONutil.Encoder.sep,&lt;br /&gt;
                                               &amp;quot;\\n&amp;quot; )&lt;br /&gt;
                                        :gsub( JSONutil.Encoder.stab,&lt;br /&gt;
                                               &amp;quot;\\t&amp;quot; )&lt;br /&gt;
                                j = i + stub:len()&lt;br /&gt;
                                s = string.format( &amp;quot;%s%s%s&amp;quot;,&lt;br /&gt;
                                                   start, stub, suffix )&lt;br /&gt;
                            else&lt;br /&gt;
                                s = start .. suffix&lt;br /&gt;
                            end&lt;br /&gt;
                            j = j + 1&lt;br /&gt;
                            break   -- while j&lt;br /&gt;
                        else&lt;br /&gt;
                            j = j + 2&lt;br /&gt;
                        end&lt;br /&gt;
                    else&lt;br /&gt;
                        r = &amp;quot;QouteEnd&amp;quot;&lt;br /&gt;
                        s = mw.text.trim( s:sub( i ) )&lt;br /&gt;
                        s = mw.ustring.sub( s, 1, JSONutil.more )&lt;br /&gt;
                        i = false&lt;br /&gt;
                    end&lt;br /&gt;
                end   -- while j&lt;br /&gt;
            else&lt;br /&gt;
                r = &amp;quot;Qoute&amp;quot;&lt;br /&gt;
                s = mw.text.trim( s:sub( i ) )&lt;br /&gt;
                s = mw.ustring.sub( s, 1, JSONutil.more )&lt;br /&gt;
                i = false&lt;br /&gt;
            end&lt;br /&gt;
        elseif not r then&lt;br /&gt;
            stub = s:sub( j )&lt;br /&gt;
            if stub:find( &amp;#039;[^&amp;quot;]*,%s*[%]}]&amp;#039; ) then&lt;br /&gt;
                r = &amp;quot;CommaEnd&amp;quot;&lt;br /&gt;
                s = mw.text.trim( stub )&lt;br /&gt;
                s = mw.ustring.sub( s, 1, JSONutil.more )&lt;br /&gt;
            else&lt;br /&gt;
                framework( stub )&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end   -- while i&lt;br /&gt;
    if not r   and   ( m ~= 0  or  n ~= 0 ) then&lt;br /&gt;
        if m ~= 0 then&lt;br /&gt;
            s = &amp;quot;}&amp;quot;&lt;br /&gt;
            if m &amp;gt; 0 then&lt;br /&gt;
                r = &amp;quot;BracketCloseLack&amp;quot;&lt;br /&gt;
                j = m&lt;br /&gt;
            elseif m &amp;lt; 0 then&lt;br /&gt;
                r = &amp;quot;BracketClosePlus&amp;quot;&lt;br /&gt;
                j = -m&lt;br /&gt;
            end&lt;br /&gt;
        else&lt;br /&gt;
            s = &amp;quot;]&amp;quot;&lt;br /&gt;
            if n &amp;gt; 0 then&lt;br /&gt;
                r = &amp;quot;BracketCloseLack&amp;quot;&lt;br /&gt;
                j = n&lt;br /&gt;
            else&lt;br /&gt;
                r = &amp;quot;BracketClosePlus&amp;quot;&lt;br /&gt;
                j = -n&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        if j &amp;gt; 1 then&lt;br /&gt;
            s =  string.format( &amp;quot;%d %s&amp;quot;, j, s )&lt;br /&gt;
        end&lt;br /&gt;
    elseif not ( r or last ) then&lt;br /&gt;
        stub = suffix or apply or &amp;quot;&amp;quot;&lt;br /&gt;
        j    = stub:find( &amp;quot;/&amp;quot;, 1, true )&lt;br /&gt;
        if j then&lt;br /&gt;
            i, stub = pcall( free, stub, j, free )&lt;br /&gt;
        else&lt;br /&gt;
            i = true&lt;br /&gt;
        end&lt;br /&gt;
        stub = mw.text.trim( stub )&lt;br /&gt;
        if i then&lt;br /&gt;
            if stub:sub( - 1 ) ~= &amp;quot;}&amp;quot; then&lt;br /&gt;
                r = &amp;quot;Trailing&amp;quot;&lt;br /&gt;
                s = stub:match( &amp;quot;%}%s*(%S[^%}]*)$&amp;quot; )&lt;br /&gt;
                if s then&lt;br /&gt;
                    s = mw.ustring.sub( s, 1, JSONutil.more )&lt;br /&gt;
                else&lt;br /&gt;
                    s = mw.ustring.sub( stub,  - JSONutil.more )&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        else&lt;br /&gt;
            r = &amp;quot;CommentEnd&amp;quot;&lt;br /&gt;
            s = mw.ustring.sub( stub, 1, JSONutil.more )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if r and s then&lt;br /&gt;
        s = s:gsub( JSONutil.Encoder.sep,  &amp;quot; &amp;quot; )&lt;br /&gt;
        s = mw.text.encode( s ):gsub( &amp;quot;|&amp;quot;, &amp;quot;&amp;amp;#124;&amp;quot; )&lt;br /&gt;
    end&lt;br /&gt;
    return r, s&lt;br /&gt;
end -- JSONutil.fair()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JSONutil.fault = function ( alert, add, adapt )&lt;br /&gt;
    -- Retrieve formatted message&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     alert  -- string, with error keyword, or other text&lt;br /&gt;
    --     add    -- string|nil|false, with context&lt;br /&gt;
    --     adapt  -- function|string|table|nil|false, for I18N&lt;br /&gt;
    -- Returns string, with HTML span&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;
    local s = alert&lt;br /&gt;
    if type( s ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
        s = mw.text.trim( s )&lt;br /&gt;
        if s == &amp;quot;&amp;quot; then&lt;br /&gt;
            s = &amp;quot;EMPTY JSONutil.fault key&amp;quot;&lt;br /&gt;
        end&lt;br /&gt;
        if not s:find( &amp;quot; &amp;quot;, 1, true ) then&lt;br /&gt;
            local storage = string.format( &amp;quot;I18n/Module:%s.tab&amp;quot;,&lt;br /&gt;
                                           JSONutil.suite )&lt;br /&gt;
            local lucky, t = pcall( mw.ext.data.get, storage, &amp;quot;_&amp;quot; )&lt;br /&gt;
            if type( t ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                t = t.data&lt;br /&gt;
                if type( t ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                    local e&lt;br /&gt;
                    s = &amp;quot;err_&amp;quot; .. s&lt;br /&gt;
                    for i = 1, #t do&lt;br /&gt;
                        e = t[ i ]&lt;br /&gt;
                        if type( e ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                            if e[ 1 ] == s then&lt;br /&gt;
                                e = e[ 2 ]&lt;br /&gt;
                                if type( e ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                                    local q = type( adapt )&lt;br /&gt;
                                    if q == &amp;quot;function&amp;quot; then&lt;br /&gt;
                                        s = adapt( e, s )&lt;br /&gt;
                                        t = false&lt;br /&gt;
                                    elseif q == &amp;quot;string&amp;quot; then&lt;br /&gt;
                                        t = mw.text.split( adapt, &amp;quot;%s+&amp;quot; )&lt;br /&gt;
                                    elseif q == &amp;quot;table&amp;quot; then&lt;br /&gt;
                                        t = adapt&lt;br /&gt;
                                    else&lt;br /&gt;
                                        t = { }&lt;br /&gt;
                                    end&lt;br /&gt;
                                    if t then&lt;br /&gt;
                                        table.insert( t, Fallback() )&lt;br /&gt;
                                        table.insert( t, &amp;quot;en&amp;quot; )&lt;br /&gt;
                                        for k = 1, #t do&lt;br /&gt;
                                            q = e[ t[ k ] ]&lt;br /&gt;
                                            if type( q ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
                                                s = q&lt;br /&gt;
                                                break   -- for k&lt;br /&gt;
                                            end&lt;br /&gt;
                                        end   -- for k&lt;br /&gt;
                                    end&lt;br /&gt;
                                else&lt;br /&gt;
                                    s = &amp;quot;JSONutil.fault I18N bad #&amp;quot; ..&lt;br /&gt;
                                        tostring( i )&lt;br /&gt;
                                end&lt;br /&gt;
                                break   -- for i&lt;br /&gt;
                            end&lt;br /&gt;
                        else&lt;br /&gt;
                            break   -- for i&lt;br /&gt;
                        end&lt;br /&gt;
                    end   -- for i&lt;br /&gt;
                else&lt;br /&gt;
                    s = &amp;quot;INVALID JSONutil.fault I18N corrupted&amp;quot;&lt;br /&gt;
                end&lt;br /&gt;
            else&lt;br /&gt;
                s = &amp;quot;INVALID JSONutil.fault commons:Data: &amp;quot; .. type( t )&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        s = &amp;quot;INVALID JSONutil.fault key: &amp;quot; .. tostring( s )&lt;br /&gt;
    end&lt;br /&gt;
    if type( add ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
        s = string.format( &amp;quot;%s &amp;amp;#8211; %s&amp;quot;, s, add )&lt;br /&gt;
    end&lt;br /&gt;
    e:wikitext( s )&lt;br /&gt;
    return tostring( e )&lt;br /&gt;
end -- JSONutil.fault()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JSONutil.fetch = function ( apply, always, adapt )&lt;br /&gt;
    -- Retrieve JSON data, or error message&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     apply   -- string, with presumable JSON text&lt;br /&gt;
    --     always  -- true, if apply is expected to need preprocessing&lt;br /&gt;
    --     adapt   -- function|string|table|nil|false, for I18N&lt;br /&gt;
    -- Returns table, with data, or string, with error as HTML span&lt;br /&gt;
    local lucky, r&lt;br /&gt;
    if not always then&lt;br /&gt;
        lucky, r = pcall( mw.text.jsonDecode, apply )&lt;br /&gt;
    end&lt;br /&gt;
    if not lucky then&lt;br /&gt;
        lucky, r = JSONutil.fair( apply )&lt;br /&gt;
        if lucky then&lt;br /&gt;
            r = JSONutil.fault( lucky, r, adapt )&lt;br /&gt;
        else&lt;br /&gt;
            lucky, r = pcall( mw.text.jsonDecode, r )&lt;br /&gt;
            if not lucky then&lt;br /&gt;
                r = JSONutil.fault( r, false, adapt )&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- JSONutil.fetch()&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&lt;br /&gt;
    --                         or &amp;quot;wikidata&amp;quot; or &amp;quot;~&amp;quot; or &amp;quot;@&amp;quot; or false&lt;br /&gt;
    -- Postcondition:&lt;br /&gt;
    --     Returns  string  -- with queried version/item, also if problem&lt;br /&gt;
    --              false   -- if appropriate&lt;br /&gt;
    -- 2020-08-17&lt;br /&gt;
    local since = atleast&lt;br /&gt;
    local last    = ( since == &amp;quot;~&amp;quot; )&lt;br /&gt;
    local linked  = ( since == &amp;quot;@&amp;quot; )&lt;br /&gt;
    local link    = ( since == &amp;quot;item&amp;quot; )&lt;br /&gt;
    local r&lt;br /&gt;
    if last  or  link  or  linked  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 suited = string.format( &amp;quot;Q%d&amp;quot;, item )&lt;br /&gt;
            if link then&lt;br /&gt;
                r = suited&lt;br /&gt;
            else&lt;br /&gt;
                local entity = mw.wikibase.getEntity( suited )&lt;br /&gt;
                if type( entity ) == &amp;quot;table&amp;quot; then&lt;br /&gt;
                    local seek = Failsafe.serialProperty or &amp;quot;P348&amp;quot;&lt;br /&gt;
                    local vsn  = entity:formatPropertyValues( seek )&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;
                        elseif linked then&lt;br /&gt;
                            if mw.title.getCurrentTitle().prefixedText&lt;br /&gt;
                               ==  mw.wikibase.getSitelink( suited ) then&lt;br /&gt;
                                r = false&lt;br /&gt;
                            else&lt;br /&gt;
                                r = suited&lt;br /&gt;
                            end&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;
    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;
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 -- p.failsafe&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p.encodeArray = function ( frame )&lt;br /&gt;
    return JSONutil.Encoder.Array( frame:getParent().args,&lt;br /&gt;
                                   frame.args.type,&lt;br /&gt;
                                   frame.args.error == &amp;quot;1&amp;quot; )&lt;br /&gt;
end -- p.encodeArray&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p.encodeComponent = function ( frame )&lt;br /&gt;
    return JSONutil.Encoder.Component( frame.args.sign,&lt;br /&gt;
                                       frame.args.value,&lt;br /&gt;
                                       frame.args.type,&lt;br /&gt;
                                       flip( frame ),&lt;br /&gt;
                                       frame.args.error == &amp;quot;1&amp;quot; )&lt;br /&gt;
end -- p.encodeComponent&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p.encodeHash = function ( frame )&lt;br /&gt;
    return JSONutil.Encoder.Hash( frame:getParent().args,&lt;br /&gt;
                                  frame.args )&lt;br /&gt;
end -- p.encodeHash&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p.encodeI18N = function ( frame )&lt;br /&gt;
    return JSONutil.Encoder.I18N( frame:getParent().args,&lt;br /&gt;
                                  flip( frame ) )&lt;br /&gt;
end -- p.encodeI18N&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p.encodeObject = function ( frame )&lt;br /&gt;
    return JSONutil.Encoder.object( flat( frame.args[ 1 ] ),&lt;br /&gt;
                                    flip( frame ) )&lt;br /&gt;
end -- p.encodeObject&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p.encodePolyglott = function ( frame )&lt;br /&gt;
    return JSONutil.Encoder.Polyglott( flat( frame.args[ 1 ] ),&lt;br /&gt;
                                       flip( frame ) )&lt;br /&gt;
end -- p.encodePolyglott&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p.JSONutil = function ()&lt;br /&gt;
    -- Module interface&lt;br /&gt;
    return JSONutil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>__de&gt;PerfektesChaos</name></author>
	</entry>
</feed>