local function format( analyze, options )
-- Check validity of a value
-- Precondition:
-- analyze -- string to be analyzed
-- options -- table or nil; optional details
-- options.say
-- options.min
-- options.max
-- Postcondition:
-- Return string with error message as configured;
-- false if valid or no answer permitted
-- Uses:
-- feasible
-- failure
local r = feasible( analyze, options, false )
local show
if options.min and not r then
if type( options.min ) == "number" then
if type( options.max ) == "number" then
if options.max < options.min then
r = failure( "minmax",
string.format( "%d > %d",
options.min,
options.max ),
options )
end
end
if #analyze < options.min and not r then
show = " <" .. options.min
if options.say then
show = string.format( "%s &quot;%s&quot;", show, options.say )
end
r = failure( "tooShort", show, options )
end
else
r = failure( "invalidPar", "min", options )
end
end
if options.max and not r then
if type( options.max ) == "number" then
if #analyze > options.max then
show = " >" .. options.max
if options.say then
show = string.format( "%s &quot;%s&quot;", show, options.say )
end
r = failure( "tooLong", show, options )
end
else
r = failure( "invalidPar", "max", options )
end
end
return r
end -- format  
local function formatted( assignment, access, options )
-- Check validity of one particular parameter in a collection
-- Precondition:
-- assignment -- collection
-- access -- id of parameter in collection
-- options -- table or nil; optional details
-- Postcondition:
-- Return string with error message as configured;
-- false if valid or no answer permitted
-- Uses:
-- mw.text.trim
-- format
-- failure
local r = false
if type( assignment ) == "table" then
local story = assignment.args[ access ] or ""
if type( access ) == "number" then
story = mw.text.trim( story )
end
if type( options ) ~= "table" then
options = { }
end
options.say = access
r = format( story, options )
end
return r
end -- formatted  
local function furnish( , action )
-- Prepare #invoke evaluation of .assert or .valid
-- Precondition:
-- -- object; #invoke environment
-- action -- "assert" or "valid"
-- Postcondition:
-- Return string with error message or ""
-- Uses:
-- form
-- failure
-- finalize
-- TemplatePar.valid
-- TemplatePar.assert
local options = { mandatory = { "1" },
optional = { "2",
"cat",
"errNS",
"low",
"max",
"min",
"format",
"preview",
"template" },
template = string.format( "&#35;invoke:%s|%s|",
"TemplatePar",
action )
}
local r = form( false, options, )
if not r then
local s
options = { cat = .args.cat,
errNS = .args.errNS,
low = .args.low,
format = .args.format,
preview = .args.preview,
template = .args.template
}
options = figure( .args[ 2 ], options )
if type( .args.min ) == "string" then
s = .args.min:match( "^%s*([0-9]+)%s*$" )
if s then
options.min = tonumber( s )
else
r = failure( "invalidPar",
"min=" .. .args.min,
options )
end
end
if type( .args.max ) == "string" then
s = .args.max:match( "^%s*([1-9][0-9]*)%s*$" )
if s then
options.max = tonumber( s )
else
r = failure( "invalidPar",
"max=" .. .args.max,
options )
end
end
if r then
r = finalize( r, options )
else
s = .args[ 1 ] or ""
r = tonumber( s )
if ( r ) then
s = r
end
if action == "valid" then
r = TemplatePar.valid( s, options )
elseif action == "assert" then
r = TemplatePar.assert( s, "", options )
end
end
end
return r or ""
end -- furnish  
TemplatePar.assert = function ( analyze, append, options )
-- Perform parameter analysis on a single string
-- Precondition:
-- analyze -- string to be analyzed
-- append -- string: append error message, prepending  
-- false or nil: throw error with message
-- options -- table; optional details
-- Postcondition:
-- Return string with error message as configured;
-- false if valid
-- Uses:
-- format
local r = format( analyze, options )
if ( r ) then
if ( type( append ) == "string" ) then
if ( append ~= "" ) then
r = string.format( "%s
%s", append, r )
end
else
error( r, 0 )
end
end
return r
end -- TemplatePar.assert  
TemplatePar.check = function ( options )
-- Run parameter analysis on current template environment
-- Precondition:
-- options -- table or nil; optional details
-- options.mandatory
-- options.optional
-- Postcondition:
-- Return string with error message as configured;
-- false if valid
-- Uses:
-- form
return form( true, options, false )
end -- TemplatePar.check  
TemplatePar.count = function
-- Return number of template parameters
-- Postcondition:
-- Return number, starting at 0
-- Uses:
-- mw.getCurrentFrame
-- :getParent
local k, v
local r = 0
local t = mw.getCurrentFrame:getParent
local o = t.args
for k, v in pairs( o ) do
r = r + 1
end -- for k, v
return r
end -- TemplatePar.count  
TemplatePar.countNotEmpty = function
-- Return number of template parameters with more than whitespace
-- Postcondition:
-- Return number, starting at 0
-- Uses:
-- mw.getCurrentFrame
-- :getParent
local k, v
local r = 0
local t = mw.getCurrentFrame:getParent
local o = t.args
for k, v in pairs( o ) do
if not v:match( "^%s*$" ) then
r = r + 1
end
end -- for k, v
return r
end -- TemplatePar.countNotEmpty  
TemplatePar.downcase = function ( options )
-- Return all template parameters with downcased name
-- Precondition:
-- options -- table or nil; optional messaging details
-- Postcondition:
-- Return table, may be empty; or string with error message.
-- Uses:
-- mw.getCurrentFrame
-- :getParent
-- flat
local t = mw.getCurrentFrame:getParent
return flat( t.args, options )
end -- TemplatePar.downcase  
TemplatePar.valid = function ( access, options )
-- Check validity of one particular template parameter
-- Precondition:
-- access -- id of parameter in template transclusion
-- string or number
-- options -- table or nil; optional details
-- Postcondition:
-- Return string with error message as configured;
-- false if valid or no answer permitted
-- Uses:
-- mw.text.trim
-- TemplatePar.downcase
-- TemplatePar.framing
-- :getParent
-- formatted
-- failure
-- finalize
local r = type( access )
if r == "string" then
r = mw.text.trim( access )
if #r == 0 then
r = false
end
elseif r == "number" then
r = access
else
r = false
end
if r then
local params
if type( options ) ~= "table" then
options = { }
end
if options.low then
params = TemplatePar.downcase( options )
else
params = TemplatePar.framing:getParent
end
r = formatted( params, access, options )
else
r = failure( "noname", false, options )
end
return finalize( r, options )
end -- TemplatePar.valid  
TemplatePar.verify = function ( options )
-- Perform #invoke parameter analysis
-- Precondition:
-- options -- table or nil; optional details
-- Postcondition:
-- Return string with error message as configured;
-- false if valid
-- Uses:
-- form
return form( false, options, false )
end -- TemplatePar.verify  
TemplatePar.framing = function
-- Ensure availability of object
-- Precondition:
-- -- object; #invoke environment, or false
-- Postcondition:
-- Return object
-- Uses:
-- >< Local.
if not Local. then
if type == "table" and
type( .args ) == "table" and
type( .getParent ) == "function" and
type( :getParent ) == "table" and
type( :getParent.getParent ) == "function" and
type( :getParent:getParent ) == "nil" then
Local. =
else
Local. = mw.getCurrentFrame
end
end
return Local.
end -- TemplatePar.framing  
Failsafe.failsafe = function ( atleast )
-- Retrieve versioning and check for compliance
-- Precondition:
-- atleast -- string, with required version
-- or wikidata|item|~|@ or false
-- Postcondition:
-- Returns string -- with queried version/item, also if problem
-- false -- if appropriate
-- 2020-08-17
local since = atleast
local last = ( since == "~" )
local linked = ( since == "@" )
local link = ( since == "item" )
local r
if last or link or linked or since == "wikidata" then
local item = Failsafe.item
since = false
if type( item ) == "number" and item > 0 then
local suited = string.format( "Q%d", item )
if link then
r = suited
else
local entity = mw.wikibase.getEntity( suited )