);
end
table.insert (render_t, utilities.substitute (cfg.presentation['hidden-maint'], table.concat (maint_msgs_t, ' '))); -- wrap the group of maint messages with proper presentation and save
end  
if not no_tracking_cats then
for _, v in ipairs (z.error_cats_t) do -- append error categories
table.insert (render_t, utilities.substitute (cfg.messages['cat wikilink'], v));
end
for _, v in ipairs (z.maint_cats_t) do -- append maintenance categories
table.insert (render_t, utilities.substitute (cfg.messages['cat wikilink'], v));
end
for _, v in ipairs (z.prop_cats_t) do -- append properties categories
table.insert (render_t, utilities.substitute (cfg.messages['cat wikilink'], v));
end
end  
return table.concat (render_t); -- make a big string and done
end  
----------------------------< V A L I D A T E >--------------------------------------------------------------  
Looks for a parameter's name in one of several whitelists.  
Parameters in the whitelist can have three values:
true - active, supported parameters
false - deprecated, supported parameters
nil - unsupported parameters  
local function validate (name, cite_class, empty)
local name = tostring (name);
local enum_name; -- for enumerated parameters, is name with enumerator replaced with '#'
local state;
local function state_test (state, name) -- local function to do testing of state values
if true == state then return true; end -- valid actively supported parameter
if false == state then
if empty then return nil; end -- empty deprecated parameters are treated as unknowns
deprecated_parameter (name); -- parameter is deprecated but still supported
return true;
end
if 'tracked' == state then
local base_name = name:gsub ('%d', ''); -- strip enumerators from parameter names that have them to get the base name
utilities.add_prop_cat ('tracked-param', {base_name}, base_name); -- add a properties category; <base_name> modifies <key>
return true;
end
return nil;
end  
if name:find ('#') then -- # is a cs1|2 reserved character so parameters with # not permitted
return nil;
end  
if utilities.in_array (cite_class, whitelist.preprint_template_list ) then -- limited parameter sets allowed for these templates
state = whitelist.limited_basic_arguments[name];
if true == state_test (state, name) then return true; end  
state = whitelist.preprint_arguments[cite_class][name]; -- look in the parameter-list for the template identified by cite_class
if true == state_test (state, name) then return true; end  
-- limited enumerated parameters list
enum_name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits)
state = whitelist.limited_numbered_arguments[enum_name];
if true == state_test (state, name) then return true; end  
return false; -- not supported because not found or name is set to nil
end -- end limited parameter-set templates  
if utilities.in_array (cite_class, whitelist.unique_param_template_list) then -- experiment for template-specific parameters for templates that accept parameters from the basic argument list
state = whitelist.unique_arguments[cite_class][name]; -- look in the template-specific parameter-lists for the template identified by cite_class
if true == state_test (state, name) then return true; end
end -- if here, fall into general validation  
state = whitelist.basic_arguments[name]; -- all other templates; all normal parameters allowed
if true == state_test (state, name) then return true; end  
-- all enumerated parameters allowed
enum_name = name:gsub("%d+", "#" ); -- replace digit(s) with # (last25 becomes last#) (mw.ustring because non-Western 'local' digits)
state = whitelist.numbered_arguments[enum_name];
if true == state_test (state, name) then return true; end  
return false; -- not supported because not found or name is set to nil
end  
--[=[-------------------------< I N T E R _ W I K I _ C H E C K >----------------------------------------------  
check <value> for inter-language interwiki-link markup. <prefix> must be a MediaWiki-recognized language
code. when these values have the form (without leading colon):
label return label as plain-text
<prefix>:link return <prefix>:link as plain-text  
return value as is else  
]=]  
local function inter_wiki_check (parameter, value)
local prefix = value:match ('%[%[(%a+):'); -- get an interwiki prefix if one exists
local _;  
if prefix and cfg.inter_wiki_map[prefix:lower] then -- if prefix is in the map, needs preceding colon so
utilities.set_message ('err_bad_paramlink', parameter); -- emit an error message
_, value, _ = utilities.is_wikilink (value); -- extract label portion from wikilink
end
return value;
end  
--2 parameters. If found, then the string is possibly a
parameter that is missing its pipe. There are two tests made:
-- the first parameter has a value and whitespace separates that value from the missing pipe parameter name
-- the first parameter has no value (whitespace after the first = is trimmed by MediaWiki)
cs1|2 shares some parameter names with XML/HTML attributes: class=, title=, etc. To prevent false positives XML/HTML
tags are removed before the search.  
If a missing pipe is detected, this function adds the missing pipe maintenance category.  
local function missing_pipe_check (parameter, value)
local capture;
value = value:gsub ('%b<>', ''); -- remove XML/HTML tags because attributes: class=, title=, etc.  
capture = value:match ('%s+(%a[%w%-]+)%s*=') or value:match ('^(%a[%w%-]+)%s*='); -- find and categorize parameters with possible missing pipes
if capture and validate (capture) then -- if the capture is a valid parameter name
utilities.set_message ('err_missing_pipe', parameter);
end
end  
----------------------------< H A S _ E X T R A N E O U S _ P U N C T >--------------------------------------  
look for extraneous terminal punctuation in most parameter values; parameters listed in skip table are not checked  
local function has_extraneous_punc (param, value)
if 'number' == type (param) then
return;
end  
param = param:gsub ('%d+', '#'); -- enumerated name-list mask params allow terminal punct; normalize
if cfg.punct_skip[param] then
return; -- parameter name found in the skip table so done
end  
if value:match ('[,;:]$') then
utilities.set_message ('maint_extra_punct'); -- has extraneous punctuation; add maint cat
end
if value:match ('^=') then -- sometimes an extraneous '=' character appears ...
utilities.set_message ('maint_extra_punct'); -- has extraneous punctuation; add maint cat
end
end  
----------------------------< H A S _ E X T R A N E O U S _ U R L >------------------------------------------  
look for extraneous url parameter values; parameters listed in skip table are not checked  
local function has_extraneous_url (url_param_t)
local url_error_t = {};  
check_for_url (url_param_t, url_error_t); -- extraneous url check
if 0 ~= #url_error_t then -- non-zero when there are errors
table.sort (url_error_t);
utilities.set_message ('err_param_has_ext_link', {utilities.make_sep_list (#url_error_t, url_error_t)}); -- add this error message
end
end  
----------------------------< C I T A T I O N >--------------------------------------------------------------  
This is used by templates such as to create the actual citation text.  
local function citation
Frame = ; -- save a copy in case we need to display an error message in preview mode
local sandbox = '/sandbox' -- i18n: replace this rvalue with the name that your wiki uses to identify sandbox subpages
is_sandbox = nil ~= string.find (:getTitle, sandbox, 1, true); -- is this invoke the sandbox module?
sandbox = is_sandbox and sandbox or ''; -- use i18n sandbox to load sandbox modules when this module is the sandox; live modules else  
local pframe = :getParent
local styles;  
cfg = mw.loadData ('Module:Citation/CS1/Configuration' .. sandbox); -- load sandbox versions of support modules when ; live modules else
whitelist = mw.loadData ('Module:Citation/CS1/Whitelist' .. sandbox);