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 config = {}; -- table to store parameters from the module
for k, v in pairs( .args ) do -- get parameters from the
config[k] = v;
-- args[k] = v; -- crude debug support that allows us to render a citation from module ; skips parameter validation; TODO: keep?
end
-- i18n: set the name that your wiki uses to identify sandbox subpages from sandbox template invoke (or can be set here)
local sandbox = ((config.SandboxPath and '' ~= config.SandboxPath) and config.SandboxPath) or '/sandbox'; -- sandbox path from
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);
utilities = require ('Module:Citation/CS1/Utilities' .. sandbox);
validation = require ('Module:Citation/CS1/Date_validation' .. sandbox);
identifiers = require ('Module:Citation/CS1/Identifiers' .. sandbox);
metadata = require ('Module:Citation/CS1/COinS' .. sandbox);
styles = 'Module:Citation/CS1' .. sandbox .. '/styles.css';  
utilities.set_selected_modules (cfg); -- so that functions in Utilities can see the selected cfg tables
identifiers.set_selected_modules (cfg, utilities); -- so that functions in Identifiers can see the selected cfg tables and selected Utilities module
validation.set_selected_modules (cfg, utilities); -- so that functions in Date validataion can see selected cfg tables and the selected Utilities module
metadata.set_selected_modules (cfg, utilities); -- so that functions in COinS can see the selected cfg tables and selected Utilities module  
z = utilities.z; -- table of error and category tables in Module:Citation/CS1/Utilities  
is_preview_mode = not utilities.is_set (:preprocess (''));  
local args = {}; -- table where we store all of the template's arguments
local suggestions = {}; -- table where we store suggestions if we need to loadData them
local error_text; -- used as a flag  
local capture; -- the single supported capture when matching unknown parameters using patterns
local empty_unknowns = {}; -- sequence table to hold empty unknown params for error message listing
for k, v in pairs( pframe.args ) do -- get parameters from the parent (template)
v = mw.ustring.gsub (v, '^%s*(.-)%s*$', '%1'); -- trim leading/trailing whitespace; when v is only whitespace, becomes empty string
if v ~= '' then
if ('string' == type (k)) then
k = mw.ustring.gsub (k, '%d', cfg.date_names.local_digits); -- for enumerated parameters, translate 'local' digits to Western 0-9
end
if not validate( k, config.CitationClass ) then
if type (k) ~= 'string' then -- exclude empty numbered parameters
if v:match("%S+") ~= nil then
error_text = utilities.set_message ('err_text_ignored', {v});
end
elseif validate (k:lower, config.CitationClass) then
error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, k:lower}); -- suggest the lowercase version of the parameter
else
if nil == suggestions.suggestions then -- if this table is nil then we need to load it
suggestions = mw.loadData ('Module:Citation/CS1/Suggestions' .. sandbox); --load sandbox version of suggestion module when ; live module else
end
for pattern, param in pairs (suggestions.patterns) do -- loop through the patterns to see if we can suggest a proper parameter
capture = k:match (pattern); -- the whole match if no capture in pattern else the capture if a match
if capture then -- if the pattern matches
param = utilities.substitute (param, capture); -- add the capture to the suggested parameter (typically the enumerator)
if validate (param, config.CitationClass) then -- validate the suggestion to make sure that the suggestion is supported by this template (necessary for limited parameter lists)
error_text = utilities.set_message ('err_parameter_ignored_suggest', {k, param}); -- set the suggestion error message
else
error_text = utilities.set_message ('err_parameter_ignored', {k}); -- suggested param not supported by this template
v = ''; -- unset
end
end
end
if not utilities.is_set (error_text) then -- couldn't match with a pattern, is there an explicit suggestion?
if (suggestions.suggestions[ k:lower ] ~= nil) and validate (suggestions.suggestions[ k:lower ], config.CitationClass) then
utilities.set_message ('err_parameter_ignored_suggest', {k, suggestions.suggestions[ k:lower ]});
else
utilities.set_message ('err_parameter_ignored', {k});
v = ''; -- unset value assigned to unrecognized parameters (this for the limited parameter lists)
end
end
end
end  
args[k] = v; -- save this parameter and its value  
elseif not utilities.is_set (v) then -- for empty parameters
if not validate (k, config.CitationClass, true) then -- is this empty parameter a valid parameter
k = ('' == k) and '(empty string)' or k; -- when k is empty string (or was space(s) trimmed to empty string), replace with descriptive text
table.insert (empty_unknowns, utilities.wrap_style ('parameter', k)); -- format for error message and add to the list
end
-- crude debug support that allows us to render a citation from module TODO: keep?
-- elseif args[k] ~= nil or (k == 'postscript') then -- when args[k] has a value from (we don't normally do that)
-- args[k] = v; -- overwrite args[k] with empty string from pframe.args[k] (template ); v is empty string here
end -- not sure about the postscript bit; that gets handled in parameter validation; historical artifact?
end  
if 0 ~= #empty_unknowns then -- create empty unknown error message
utilities.set_message ('err_param_unknown_empty', {
1 == #empty_unknowns and '' or 's',
utilities.make_sep_list (#empty_unknowns, empty_unknowns)
});
end  
local url_param_t = {};  
for k, v in pairs( args ) do